diff --git a/.eslintrc b/.eslintrc index f9dfbf4..f70b205 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,306 +1,273 @@ { - "env": { - "browser": true, - "es6": true, - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended" - ], - "parser": "babel-eslint", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 2018, - "ecmaFeatures": { - "jsx": true + "env": { + "browser": true, + "es6": true, + "node": true + }, + "extends": [ + "standard", + "eslint:recommended", + "plugin:react/recommended", + "plugin:unicorn/recommended", + "prettier", + "prettier/standard", + "prettier/unicorn" + ], + "parser": "babel-eslint", + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 2018, + "ecmaFeatures": { + "jsx": true + } + }, + "globals": { + "__": true + }, + "plugins": ["babel", "react", "prettier", "standard", "unicorn"], + "rules": { + "accessor-pairs": "error", + "array-bracket-newline": "error", + "array-bracket-spacing": ["error", "never"], + "array-callback-return": "off", + "array-element-newline": "off", + "arrow-body-style": "off", + "arrow-parens": "off", + "arrow-spacing": [ + "error", + { + "after": true, + "before": true } - }, - "globals": { - "__": true - }, - "plugins": [ - "babel", - "react" ], - "rules": { - "accessor-pairs": "error", - "array-bracket-newline": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "array-callback-return": "off", - "array-element-newline": "off", - "arrow-body-style": "off", - "arrow-parens": "off", - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-scoped-var": "error", - "block-spacing": "error", - "brace-style": "off", - "callback-return": "off", - "camelcase": "off", - "capitalized-comments": "off", - "class-methods-use-this": "off", - "comma-dangle": "off", - "comma-spacing": "off", - "comma-style": [ - "error", - "last" - ], - "complexity": "error", - "computed-property-spacing": [ - "error", - "never" - ], - "consistent-return": "off", - "consistent-this": "off", - "curly": "off", - "default-case": "error", - "dot-location": [ - "error", - "property" - ], - "dot-notation": "off", - "eol-last": "error", - "eqeqeq": "error", - "for-direction": "error", - "func-call-spacing": "error", - "func-name-matching": "error", - "func-names": "off", - "func-style": "off", - "function-paren-newline": "off", - "generator-star-spacing": "error", - "getter-return": "error", - "global-require": "off", - "guard-for-in": "off", - "handle-callback-err": "off", - "id-blacklist": "error", - "id-length": "off", - "id-match": "error", - "indent": "off", - "indent-legacy": "off", - "init-declarations": "off", - "jsx-quotes": "error", - "key-spacing": "off", - "keyword-spacing": "off", - "line-comment-position": "off", - "linebreak-style": [ - "error", - "unix" - ], - "lines-around-comment": "error", - "lines-around-directive": "error", - "max-depth": "error", - "max-len": "off", - "max-lines": "off", - "max-params": "off", - "max-statements": "off", - "max-statements-per-line": "off", - "multiline-ternary": [ - "error", - "never" - ], - "new-parens": "off", - "newline-after-var": "off", - "newline-before-return": "off", - "newline-per-chained-call": "off", - "no-alert": "error", - "no-array-constructor": "error", - "no-await-in-loop": "error", - "no-bitwise": "error", - "no-buffer-constructor": "error", - "no-caller": "error", - "no-catch-shadow": "error", - "no-confusing-arrow": "error", - "no-console": "off", - "no-continue": "off", - "no-debugger": "warn", - "no-div-regex": "error", - "no-duplicate-imports": "error", - "no-else-return": 2, - "no-empty-function": "off", - "no-eq-null": "error", - "no-eval": "off", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-label": "error", - "no-extra-parens": "off", - "no-floating-decimal": "error", - "no-implicit-coercion": [ - "error", - { - "allow": ["!!"] - } - ], - "no-implicit-globals": "error", - "no-implied-eval": "error", - "no-inline-comments": "off", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-this": "off", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-lonely-if": "off", - "no-loop-func": "off", - "no-magic-numbers": "off", - "no-mixed-operators": "error", - "no-mixed-requires": "error", - "no-multi-assign": "error", - "no-multi-spaces": "off", - "no-multi-str": "error", - "no-multiple-empty-lines": "error", - "no-native-reassign": "error", - "no-negated-condition": "off", - "no-negated-in-lhs": "error", - "no-nested-ternary": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-wrappers": "error", - "no-octal-escape": "error", - "no-param-reassign": "off", - "no-path-concat": "error", - "no-plusplus": "off", - "no-process-env": "off", - "no-process-exit": "off", - "no-proto": "error", - "no-prototype-builtins": "off", - "no-restricted-globals": "error", - "no-restricted-imports": "error", - "no-restricted-modules": "error", - "no-restricted-properties": "error", - "no-restricted-syntax": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-script-url": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow": "off", - "no-shadow-restricted-names": "error", - "no-spaced-func": "error", - "no-sync": "off", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-ternary": "off", - "no-throw-literal": "error", - "no-trailing-spaces": "off", - "no-undef-init": "error", - "no-undefined": "off", - "no-underscore-dangle": "off", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": "error", - "no-unused-expressions": "error", - "no-unused-vars": ["error", { + "block-scoped-var": "error", + "block-spacing": "error", + "brace-style": "off", + "callback-return": "off", + "camelcase": "off", + "capitalized-comments": "off", + "class-methods-use-this": "off", + "comma-dangle": "error", + "comma-spacing": "off", + "comma-style": ["error", "last"], + "complexity": "error", + "computed-property-spacing": ["error", "never"], + "consistent-return": "off", + "consistent-this": "off", + "curly": "off", + "default-case": "error", + "dot-location": ["error", "property"], + "dot-notation": "off", + "eol-last": "error", + "eqeqeq": "error", + "for-direction": "error", + "func-call-spacing": "error", + "func-name-matching": "error", + "func-names": "off", + "func-style": "off", + "function-paren-newline": "off", + "generator-star-spacing": "error", + "getter-return": "error", + "global-require": "off", + "guard-for-in": "off", + "handle-callback-err": "off", + "id-blacklist": "error", + "id-length": "off", + "id-match": "error", + "indent": ["error", 2], + "indent-legacy": "off", + "init-declarations": "off", + "jsx-quotes": "error", + "key-spacing": "off", + "keyword-spacing": "off", + "line-comment-position": "off", + "linebreak-style": ["error", "unix"], + "lines-around-comment": "error", + "lines-around-directive": "error", + "max-depth": "error", + "max-len": "off", + "max-lines": "off", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": "off", + "multiline-ternary": ["error", "never"], + "new-parens": "off", + "newline-after-var": "off", + "newline-before-return": "off", + "newline-per-chained-call": "off", + "no-alert": "error", + "no-array-constructor": "error", + "no-await-in-loop": "error", + "no-bitwise": "error", + "no-buffer-constructor": "error", + "no-caller": "error", + "no-catch-shadow": "error", + "no-confusing-arrow": "error", + "no-console": "off", + "no-continue": "off", + "no-debugger": "warn", + "no-div-regex": "error", + "no-duplicate-imports": "error", + "no-else-return": 2, + "no-empty-function": "off", + "no-eq-null": "error", + "no-eval": "off", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-label": "error", + "no-extra-parens": "off", + "no-floating-decimal": "error", + "no-implicit-coercion": [ + "error", + { + "allow": ["!!"] + } + ], + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-inline-comments": "off", + "no-inner-declarations": ["error", "functions"], + "no-invalid-this": "off", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "off", + "no-loop-func": "off", + "no-magic-numbers": "off", + "no-mixed-operators": "error", + "no-mixed-requires": "error", + "no-multi-assign": "error", + "no-multi-spaces": "off", + "no-multi-str": "error", + "no-multiple-empty-lines": "error", + "no-native-reassign": "error", + "no-negated-condition": "off", + "no-negated-in-lhs": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-require": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-param-reassign": "off", + "no-path-concat": "error", + "no-plusplus": "off", + "no-process-env": "off", + "no-process-exit": "off", + "no-proto": "error", + "no-prototype-builtins": "off", + "no-restricted-globals": "error", + "no-restricted-imports": "error", + "no-restricted-modules": "error", + "no-restricted-properties": "error", + "no-restricted-syntax": "error", + "no-return-assign": "error", + "no-return-await": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": "off", + "no-shadow-restricted-names": "error", + "no-spaced-func": "error", + "no-sync": "off", + "no-tabs": "error", + "no-template-curly-in-string": "error", + "no-ternary": "off", + "no-throw-literal": "error", + "no-trailing-spaces": "off", + "no-undef-init": "error", + "no-undefined": "off", + "no-underscore-dangle": "off", + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" - }], - "no-use-before-define": "off", - "no-useless-call": "off", - "no-useless-computed-key": "error", - "no-useless-concat": "error", - "no-useless-constructor": "error", - "no-useless-escape": "off", - "no-useless-rename": "error", - "no-useless-return": "off", - "no-var": "off", - "no-void": "error", - "no-warning-comments": "off", - "no-whitespace-before-property": "error", - "no-with": "error", - "nonblock-statement-body-position": "error", - "object-curly-newline": "off", - "object-curly-spacing": [ - "off" - ], - "object-property-newline": "off", - "object-shorthand": "off", - "one-var": "off", - "one-var-declaration-per-line": "off", - "operator-assignment": "off", - "operator-linebreak": "error", - "padded-blocks": "off", - "padding-line-between-statements": "error", - "prefer-arrow-callback": "off", - "prefer-const": "off", - "prefer-destructuring": "off", - "prefer-numeric-literals": "error", - "prefer-promise-reject-errors": "error", - "prefer-reflect": "off", - "prefer-rest-params": "off", - "prefer-spread": "off", - "prefer-template": "off", - "quote-props": "off", - "quotes": "off", - "radix": "error", - "require-await": "off", - "require-jsdoc": "off", - "rest-spread-spacing": "error", - "semi": "error", - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "semi-style": [ - "error", - "last" - ], - "sort-imports": "off", - "sort-keys": "off", - "sort-vars": "off", - "space-before-blocks": "off", - "space-before-function-paren": "off", - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "off", - "space-unary-ops": "error", - "spaced-comment": "off", - "strict": "error", - "switch-colon-spacing": "error", - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": "error", - "unicode-bom": [ - "error", - "never" - ], - "valid-jsdoc": "error", - "vars-on-top": "off", - "wrap-iife": "error", - "wrap-regex": "error", - "yield-star-spacing": "error", - "yoda": [ - "error", - "never" - ], - "react/jsx-boolean-value": 0, - "react/jsx-closing-bracket-location": 1, - "react/jsx-curly-spacing": "off", - "react/jsx-indent-props": [1, 2], - "react/jsx-no-undef": 1, - "react/jsx-uses-react": 1, - "react/jsx-uses-vars": 1, - "react/react-in-jsx-scope": 1, - "react/prefer-es6-class": 1, - "react/jsx-no-bind": 1 - } - } \ No newline at end of file + } + ], + "no-use-before-define": "off", + "no-useless-call": "off", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-escape": "off", + "no-useless-rename": "error", + "no-useless-return": "off", + "no-var": "off", + "no-void": "error", + "no-warning-comments": "off", + "no-whitespace-before-property": "error", + "no-with": "error", + "nonblock-statement-body-position": "error", + "object-curly-newline": "off", + "object-curly-spacing": ["off"], + "object-property-newline": "off", + "object-shorthand": "off", + "one-var": "off", + "one-var-declaration-per-line": "off", + "operator-assignment": "off", + "operator-linebreak": "error", + "padded-blocks": "off", + "padding-line-between-statements": "error", + "prefer-arrow-callback": "off", + "prefer-const": "off", + "prefer-destructuring": "off", + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "prefer-reflect": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "prefer-template": "off", + "quote-props": "off", + "quotes": "off", + "radix": "error", + "require-await": "off", + "require-jsdoc": "off", + "rest-spread-spacing": "error", + "semi": "error", + "semi-spacing": [ + "error", + { + "after": true, + "before": false + } + ], + "semi-style": ["error", "last"], + "sort-imports": "off", + "sort-keys": "off", + "sort-vars": "off", + "space-before-blocks": "off", + "space-before-function-paren": "off", + "space-in-parens": ["error", "never"], + "space-infix-ops": "off", + "space-unary-ops": "error", + "spaced-comment": "off", + "strict": "error", + "switch-colon-spacing": "error", + "symbol-description": "error", + "template-curly-spacing": ["error", "never"], + "template-tag-spacing": "error", + "unicode-bom": ["error", "never"], + "valid-jsdoc": "error", + "vars-on-top": "off", + "wrap-iife": "error", + "wrap-regex": "error", + "yield-star-spacing": "error", + "yoda": ["error", "never"], + "react/jsx-boolean-value": 0, + "react/jsx-closing-bracket-location": 1, + "react/jsx-curly-spacing": "off", + "react/jsx-indent-props": [1, 2], + "react/jsx-no-undef": 1, + "react/jsx-uses-react": 1, + "react/jsx-uses-vars": 1, + "react/react-in-jsx-scope": 1, + "react/prefer-es6-class": 1, + "react/jsx-no-bind": 1 + } +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..d196722 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +trailingComma: "none" +printWidth: 120 +useTabs: false +semi: true +arrowParens: "avoid" +tabWidth: 2 +endOfLine: "lf" +singleQuote: true \ No newline at end of file diff --git a/app/components/AdminView.js b/app/components/AdminView.js index a5cc188..34cbf9c 100644 --- a/app/components/AdminView.js +++ b/app/components/AdminView.js @@ -9,6 +9,6 @@ const AdminView = () => { ); }; -AdminView.displayName = "AdminView"; +AdminView.displayName = 'AdminView'; export default AdminView; diff --git a/app/components/Voting.js b/app/components/Voting.js index 97bae98..0e339c7 100644 --- a/app/components/Voting.js +++ b/app/components/Voting.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import CssBaseline from '@material-ui/core/CssBaseline'; import LinearProgress from '@material-ui/core/LinearProgress'; import { VotingContext } from '../context'; -import { Route, Switch, withRouter } from "react-router-dom"; +import { Route, Switch, withRouter } from 'react-router-dom'; import AdminView from '../components/AdminView'; import TitleScreen from './flow/TitleScreen'; import LearnAboutBallots from './flow/LearnAboutBallots'; @@ -27,10 +27,8 @@ import PollSchedule from './flow/create/PollSchedule'; import PollReview from './flow/create/PollReview'; import PollCreationResults from './flow/create/PollCreationResults'; - - class Voting extends PureComponent { - state = { + state = { addPoll: false, pollTokenBalances: [], votes: [], @@ -42,87 +40,322 @@ class Voting extends PureComponent { }; updatePollBalance = (pollId, tokenBalance, ethBalance, votes) => { - const {pollTokenBalances} = this.state; + const { pollTokenBalances } = this.state; pollTokenBalances[pollId] = { tokenBalance, ethBalance }; - this.setState({pollTokenBalances, votes}); - } + this.setState({ pollTokenBalances, votes }); + }; + + setVotesToReview = votes => { + this.setState({ votes }); + }; - setVotesToReview = (votes) => { - this.setState({votes}); - } - setTransactionHash = (idPoll, transactionHash) => { const stHash = this.state.transactionHash; stHash[idPoll] = transactionHash; - - this.setState({transactionHash: stHash}); - } + + this.setState({ transactionHash: stHash }); + }; setTransactionPromise = (idPoll, transaction) => { const sTrx = this.state.transaction; sTrx[idPoll] = transaction; - this.setState({transaction: sTrx}); - } + this.setState({ transaction: sTrx }); + }; - setPollTransactionHash = (transactionHash) => { - this.setState({pollTransactionHash: transactionHash}); - } + setPollTransactionHash = transactionHash => { + this.setState({ pollTransactionHash: transactionHash }); + }; - setPollTransactionPromise = (transaction) => { - this.setState({pollTransaction: transaction}); - } + setPollTransactionPromise = transaction => { + this.setState({ pollTransaction: transaction }); + }; - - assignToPoll = (newData) => { + assignToPoll = newData => { const pollCr = Object.assign(this.state.pollCr, newData); - this.setState({pollCr}); - } + this.setState({ pollCr }); + }; - resetPoll = ()=>{ - this.setState({pollCr: {}}); - } + resetPoll = () => { + this.setState({ pollCr: {} }); + }; - render(){ + render() { const { addPoll, pollTokenBalances, votes, transaction, transactionHash, start, end } = this.state; return ( - - {({ getPolls, rawPolls, loading, symbol, decimals, name, replacePoll, loadPollContent, loadPollRange, loadMorePolls, start, resetPollCounter, end }) => -
- - {loading && } -
- - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> + + {({ + getPolls, + rawPolls, + loading, + symbol, + decimals, + name, + replacePoll, + loadPollContent, + loadPollRange, + loadMorePolls, + start, + resetPollCounter, + end + }) => ( +
+ + {loading && } +
+ + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + +
-
- } - + )} + - - ) + ); } } diff --git a/app/components/flow/HelpDialog.js b/app/components/flow/HelpDialog.js index 9d65952..827cdc2 100644 --- a/app/components/flow/HelpDialog.js +++ b/app/components/flow/HelpDialog.js @@ -1,61 +1,94 @@ - - import React from 'react'; - import PropTypes from 'prop-types'; - import { withStyles } from '@material-ui/core/styles'; - import Button from '@material-ui/core/Button'; - import Dialog from '@material-ui/core/Dialog'; - import ListItemText from '@material-ui/core/ListItemText'; - import ListItem from '@material-ui/core/ListItem'; - import List from '@material-ui/core/List'; - import Divider from '@material-ui/core/Divider'; - import AppBar from '@material-ui/core/AppBar'; - import Toolbar from '@material-ui/core/Toolbar'; - import IconButton from '@material-ui/core/IconButton'; - import Typography from '@material-ui/core/Typography'; - import CloseIcon from '@material-ui/icons/Close'; - import Slide from '@material-ui/core/Slide'; - +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import ListItemText from '@material-ui/core/ListItemText'; +import ListItem from '@material-ui/core/ListItem'; +import List from '@material-ui/core/List'; +import Divider from '@material-ui/core/Divider'; +import AppBar from '@material-ui/core/AppBar'; +import Toolbar from '@material-ui/core/Toolbar'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; +import CloseIcon from '@material-ui/icons/Close'; +import Slide from '@material-ui/core/Slide'; function Transition(props) { - return ; - } + return ; +} +const HelpDialog = props => ( + + + + + + + + Need help? + + + + Chat to us on Status + + Tap here:{' '} + + get.status.im/chat/public/status-snt-voting-dapp + {' '} + to chat with us.{' '} + + What are voting credits? + + Voting Credits are used to purchase votes. The amount of voting credits equals the amount of {props.symbol} you + had in the wallet address used to open the Voting Dapp when the poll was created. + + Why do I have zero voting credits? + + You have zero voting credits because the wallet used to open the voting dapp had zero {props.symbol} in it at the + time the poll was created. + + Why do votes cost more voting credits for every additional vote? + + The price of votes equals its square in voting credits. This means purchasing the first vote on a ballot costs 1 + voting credit, the second vote will require a total of 4 voting credits, the third vote will cost 9 voting credits + in total. + + This is done to prevent domination of the vote by large token holders. + How do I connect with a Tezors or Ledger? + + You may connect with a Ledger or Tezors via the metamask intergration. Information for how to connect to Trezor + can be found here:{' '} + + https://medium.com/metamask/trezor-integration-in-metamask-a8eaeae7f499 + + + + And Ledger here:{' '} + + https://medium.com/metamask/metamask-now-supports-ledger-hardware-wallets-847f4d51546 + + + + Please note that for ledger to work, the ethereum application on ledger needs to be 1.2.4 and above. Please find + instructions to do so here:{' '} + + https://support.ledgerwallet.com/hc/en-us/articles/360009576554-Ethereum-ETH- + + + Why do I need to pay ETH to vote? + + Voting is done "on-chain", this means that your vote is written to the ethereum blockchain, ensuring that your + vote is transparent and immutable. To write any data to the ethereum blockchain requires miners to validate the + transaction. Miner's require an incentive in the form of ETH to mine a transaction. + + +); -const HelpDialog = (props) => - - - - - - - Need help? - - - - Chat to us on Status - Tap here: get.status.im/chat/public/status-snt-voting-dapp to chat with us. - What are voting credits? - Voting Credits are used to purchase votes. The amount of voting credits equals the amount of {props.symbol} you had in the wallet address used to open the Voting Dapp when the poll was created. - Why do I have zero voting credits? - You have zero voting credits because the wallet used to open the voting dapp had zero {props.symbol} in it at the time the poll was created. - Why do votes cost more voting credits for every additional vote? - The price of votes equals its square in voting credits. This means purchasing the first vote on a ballot costs 1 voting credit, the second vote will require a total of 4 voting credits, the third vote will cost 9 voting credits in total. - This is done to prevent domination of the vote by large token holders. - How do I connect with a Tezors or Ledger? - You may connect with a Ledger or Tezors via the metamask intergration. Information for how to connect to Trezor can be found here: https://medium.com/metamask/trezor-integration-in-metamask-a8eaeae7f499 - And Ledger here: https://medium.com/metamask/metamask-now-supports-ledger-hardware-wallets-847f4d51546 - Please note that for ledger to work, the ethereum application on ledger needs to be 1.2.4 and above. Please find instructions to do so here: https://support.ledgerwallet.com/hc/en-us/articles/360009576554-Ethereum-ETH- - Why do I need to pay ETH to vote? - Voting is done "on-chain", this means that your vote is written to the ethereum blockchain, ensuring that your vote is transparent and immutable. To write any data to the ethereum blockchain requires miners to validate the transaction. Miner's require an incentive in the form of ETH to mine a transaction. - - - - - export default HelpDialog; - \ No newline at end of file +export default HelpDialog; diff --git a/app/components/flow/HowVotingWorks.js b/app/components/flow/HowVotingWorks.js index 29b71a5..29566d2 100644 --- a/app/components/flow/HowVotingWorks.js +++ b/app/components/flow/HowVotingWorks.js @@ -1,12 +1,12 @@ import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; +import React, { Component, Fragment } from 'react'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import CardActions from '@material-ui/core/CardActions'; import Typography from '@material-ui/core/Typography'; import { withRouter } from 'react-router-dom'; -import DappToken from 'Embark/contracts/DappToken'; -import PollManager from 'Embark/contracts/PollManager'; +import DappToken from 'Embark/contracts/DappToken'; +import PollManager from 'Embark/contracts/PollManager'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; @@ -14,12 +14,10 @@ import DialogTitle from '@material-ui/core/DialogTitle'; import utils from '../../utils/utils'; class HowVotingWorks extends Component { - state = { open: false, tip: 0 - } - + }; handleClickOpen = tip => () => { this.setState({ @@ -32,163 +30,206 @@ class HowVotingWorks extends Component { this.setState({ open: false }); }; - - componentDidUpdate(prevProps){ + componentDidUpdate(prevProps) { if (this.props.polls !== prevProps.polls && this.props.polls) { // TODO: see how to extract this. Maybe a higher order component? const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - if(poll && !poll.content){ + if (poll && !poll.content) { this.props.loadPollContent(poll); } } } checkWeb3 = async () => { - if(!window.web3){ - this.props.history.push("/wallet/" + this.props.idPoll); + if (!window.web3) { + this.props.history.push('/wallet/' + this.props.idPoll); return; } - const {history, polls, updateBalances, idPoll, decimals} = this.props; - if(!polls) return; + const { history, polls, updateBalances, idPoll, decimals } = this.props; + if (!polls) return; let cont = true; if (window.ethereum) { try { - await ethereum.enable(); - web3.setProvider(ethereum); - const accounts = await web3.eth.getAccounts(); - web3.eth.defaultAccount = accounts[0]; + await ethereum.enable(); + web3.setProvider(ethereum); + const accounts = await web3.eth.getAccounts(); + web3.eth.defaultAccount = accounts[0]; } catch (error) { cont = false; } } - if(cont){ + if (cont) { // TODO: extract this code to utils. It's repeated in ConnectYourWallt, ExternalWallet and HowVotingWorks const poll = polls.find(p => p.idPoll == idPoll); - if(!poll) return null; - - const tknVotes = await PollManager.methods.getVote(idPoll, web3.eth.defaultAccount).call({from: web3.eth.defaultAccount}); - const votes = tknVotes.map(x => Math.sqrt(parseInt( utils.fromTokenDecimals(x, decimals)))); - const tokenBalance = await DappToken.methods.balanceOfAt(web3.eth.defaultAccount, poll._startBlock).call({from: web3.eth.defaultAccount}); + if (!poll) return null; + + const tknVotes = await PollManager.methods + .getVote(idPoll, web3.eth.defaultAccount) + .call({ from: web3.eth.defaultAccount }); + const votes = tknVotes.map(x => Math.sqrt(parseInt(utils.fromTokenDecimals(x, decimals)))); + const tokenBalance = await DappToken.methods + .balanceOfAt(web3.eth.defaultAccount, poll._startBlock) + .call({ from: web3.eth.defaultAccount }); const ethBalance = await web3.eth.getBalance(web3.eth.defaultAccount); updateBalances(idPoll, tokenBalance, ethBalance, votes); history.push('/votingCredits/' + idPoll); } - } + }; render() { const props = this.props; - return
- How voting works - - { this.state.tip == 1 &&

When a vote is created, the Voting Dapp uses smart contracts to take a snapshot of all the wallets addresses which hold {this.props.symbol} and their {this.props.symbol} balances. These {this.props.symbol} balances are used to inform the number of voting credits a wallet address has. No {this.props.symbol} needs to be staked or committed, all that is required is to connect to the voting app with a wallet that had {this.props.symbol} in it before the "snapshot" was taken.

} - { this.state.tip == 2 &&

Voting credits are a representation of the {this.props.symbol} in the wallet address at the time the vote was created. When voting, the first ballot which is voted on will cost 1 voting credit. The second vote will cost an additional 3 voting credits to total 4 voting credits. Every additional vote will require its square in voting credits.

} - { this.state.tip == 3 &&

This voting process is called quadratic voting. It minimizes the effect that large token holders can have on the vote, measures the intensity of opinion and encourages a spread of voting amongst the ballots.

} - } - title={ - - { this.state.tip == 1 && Any wallet with {this.props.symbol} can vote } - { this.state.tip == 2 && You don't spend your {this.props.symbol}! } - { this.state.tip == 3 && Your vote counts } - - } - open={this.state.open} - onClose={this.handleClose} -/> - - -
- -
-
- - Any wallet with {this.props.symbol} can vote - - - When a poll is created a snapshot is taken of every wallet that holds {this.props.name} ({this.props.symbol}). - -
-
- - - -
- - -
- -
-
- - You don't spend your {this.props.symbol}! - - - Your wallet gets one voting credit for every {this.props.symbol} it holds. To cast your vote, you sign a transaction, but you only spend a small amount of ETH for the transaction fee. - -
-
- - - -
- - -
- -
-
- - Your vote counts - - - Most votes when poll ends wins! Multiple votes cost more to prevent whales from controlling the vote - -
-
- - - -
-
-
- -
- -
; - } -} - - - -class InfoDialog extends Component { - - handleClose = () => { - this.props.onClose(this.props.selectedValue); - }; - - handleListItemClick = value => { - this.props.onClose(value); - }; - - render() { - const { onClose, text, title, ...other } = this.props; - return ( - - {title} - - {text} - - - - - + +
+ How voting works + + {this.state.tip == 1 && ( +

+ When a vote is created, the Voting Dapp uses smart contracts to take a snapshot of all the wallets + addresses which hold {this.props.symbol} and their {this.props.symbol} balances. These{' '} + {this.props.symbol} balances are used to inform the number of voting credits a wallet address has. + No {this.props.symbol} needs to be staked or committed, all that is required is to connect to the + voting app with a wallet that had {this.props.symbol} in it before the "snapshot" was taken. +

+ )} + {this.state.tip == 2 && ( +

+ Voting credits are a representation of the {this.props.symbol} in the wallet address at the time the + vote was created. When voting, the first ballot which is voted on will cost 1 voting credit. The + second vote will cost an additional 3 voting credits to total 4 voting credits. Every additional + vote will require its square in voting credits. +

+ )} + {this.state.tip == 3 && ( +

+ This voting process is called quadratic voting. It minimizes the effect that large token holders can + have on the vote, measures the intensity of opinion and encourages a spread of voting amongst the + ballots. +

+ )} + + } + title={ + + {this.state.tip == 1 && Any wallet with {this.props.symbol} can vote} + {this.state.tip == 2 && You don't spend your {this.props.symbol}!} + {this.state.tip == 3 && Your vote counts} + + } + open={this.state.open} + onClose={this.handleClose} + /> + + +
+ + + +
+
+ + Any wallet with {this.props.symbol} can vote + + + When a poll is created a snapshot is taken of every wallet that holds {this.props.name} ( + {this.props.symbol}). + +
+
+ + + +
+ + +
+ + + +
+
+ + You don't spend your {this.props.symbol}! + + + Your wallet gets one voting credit for every {this.props.symbol} it holds. To cast your vote, you sign + a transaction, but you only spend a small amount of ETH for the transaction fee. + +
+
+ + + +
+ + +
+ + + +
+
+ + Your vote counts + + + Most votes when poll ends wins! Multiple votes cost more to prevent whales from controlling the vote + +
+
+ + + +
+
+
+ +
+
); } } -export default withRouter(HowVotingWorks); \ No newline at end of file +class InfoDialog extends Component { + handleClose = () => { + this.props.onClose(this.props.selectedValue); + }; + + handleListItemClick = value => { + this.props.onClose(value); + }; + + render() { + const { onClose, text, title, ...other } = this.props; + + return ( + + {title} + + + {text} + + + + + + + ); + } +} + +export default withRouter(HowVotingWorks); diff --git a/app/components/flow/LandingPage.js b/app/components/flow/LandingPage.js index c6a308b..7f58616 100644 --- a/app/components/flow/LandingPage.js +++ b/app/components/flow/LandingPage.js @@ -1,180 +1,198 @@ import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; +import React, { Component, Fragment } from 'react'; import Typography from '@material-ui/core/Typography'; -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; -import { withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom'; import utils from '../../utils/utils'; // TODO: extract to utils function pad(number, length) { - - var str = '' + number; - while (str.length < length) { - str = '0' + str; - } - - return str; - + var str = String(number); + while (str.length < length) { + str = '0' + str; } -Date.prototype.DDMMYYYY = function () { - var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); - var dd = pad(this.getDate(), 2); - - return dd + '/' + MM + '/' + yyyy ; - }; - - -class LandingPage extends Component { - - state = { - openPoll: null, - closedPoll: null - } - - componentDidMount(){ - this.loadLatestPolls(); - } - - gotoOtherPolls = (type) => () => { - this.props.resetPollCounter(); - this.props.history.push('/otherPolls/' + type); - } - - createPoll = async () => { - if(!window.web3){ - this.props.history.push("/wallet/poll-creation"); - return; - } - - let cont = true; - if (window.ethereum) { - try { - await ethereum.enable(); - web3.setProvider(ethereum); - const accounts = await web3.eth.getAccounts(); - web3.eth.defaultAccount = accounts[0]; - } catch (error) { - cont = false; - } - } - - if(cont) - this.props.history.push('/poll/create'); - } - - - loadLatestPolls = () => { - let polls = this.props.polls; - - if(polls && polls.length){ - const openPoll = polls.find(x => !x._canceled && x._endTime > (new Date()).getTime() / 1000); - if(openPoll) - EmbarkJS.Storage.get(web3.utils.toAscii(openPoll._description)).then(content => { - openPoll.content = JSON.parse(content); - this.setState({openPoll}) - - this.props.replacePoll(openPoll); - }) - - const closedPoll = polls.find(x => !x._canceled && x._endTime < (new Date()).getTime() / 1000); - if(closedPoll) - EmbarkJS.Storage.get(web3.utils.toAscii(closedPoll._description)).then(content => { - closedPoll.content = JSON.parse(content); - this.setState({closedPoll}); - this.props.replacePoll(closedPoll); - }) - } - } - - componentDidUpdate(prevProps) { - if (this.props.polls !== prevProps.polls) { - this.loadLatestPolls(); - } - } - - render(){ - const { openPoll, closedPoll } = this.state; - const { decimals } = this.props; - - if(openPoll){ - openPoll._tokenSum = 0; - openPoll._votesSum = 0; - for(let i = 0; i < openPoll._numBallots; i++){ - openPoll._tokenSum += parseInt(utils.fromTokenDecimals(openPoll._tokenTotal[i], decimals), 10); - openPoll._votesSum += parseInt(openPoll._quadraticVotes[i], 10); - } - } - - if(closedPoll){ - closedPoll._tokenSum = 0; - closedPoll._votesSum = 0; - for(let i = 0; i < closedPoll._numBallots; i++){ - closedPoll._tokenSum += parseInt(utils.fromTokenDecimals(closedPoll._tokenTotal[i], decimals), 10); - closedPoll._votesSum += parseInt(closedPoll._quadraticVotes[i], 10); - } - } - - return -
-
- - - Status {this.props.symbol} Voting - Create a poll or vote in one. Your vote helps us decide our product and community direction. -
- - { openPoll && openPoll.content && -
-

Open Polls

- - - {openPoll.content.title} - Closes: {new Date(openPoll._endTime * 1000).DDMMYYYY()} -

- Voters: {openPoll._voters}
- Total votes: {openPoll._votesSum}
- Total {this.props.symbol}: {openPoll._tokenSum} -

- VOTE NOW -
-
- -
- } - - { closedPoll && closedPoll.content && -
-

Closed Polls

- - - {closedPoll.content.title} - Closed: {new Date(closedPoll._endTime * 1000).DDMMYYYY()} -

- Voters: {closedPoll._voters}
- Total votes: {closedPoll._votesSum}
- Total {this.props.symbol}: {closedPoll._tokenSum}
-

- See results -
-
- -
- } -
- - - -
; - } + return str; } -export default withRouter(LandingPage); \ No newline at end of file +Date.prototype.DDMMYYYY = function() { + var yyyy = this.getFullYear().toString(); + var MM = pad(this.getMonth() + 1, 2); + var dd = pad(this.getDate(), 2); + + return dd + '/' + MM + '/' + yyyy; +}; + +class LandingPage extends Component { + state = { + openPoll: null, + closedPoll: null + }; + + componentDidMount() { + this.loadLatestPolls(); + } + + gotoOtherPolls = type => () => { + this.props.resetPollCounter(); + this.props.history.push('/otherPolls/' + type); + }; + + createPoll = async () => { + if (!window.web3) { + this.props.history.push('/wallet/poll-creation'); + return; + } + + let cont = true; + if (window.ethereum) { + try { + await ethereum.enable(); + web3.setProvider(ethereum); + const accounts = await web3.eth.getAccounts(); + web3.eth.defaultAccount = accounts[0]; + } catch (error) { + cont = false; + } + } + + if (cont) this.props.history.push('/poll/create'); + }; + + loadLatestPolls = () => { + let polls = this.props.polls; + + if (polls && polls.length) { + const openPoll = polls.find(x => !x._canceled && x._endTime > new Date().getTime() / 1000); + if (openPoll) + EmbarkJS.Storage.get(web3.utils.toAscii(openPoll._description)).then(content => { + openPoll.content = JSON.parse(content); + this.setState({ openPoll }); + + this.props.replacePoll(openPoll); + }); + + const closedPoll = polls.find(x => !x._canceled && x._endTime < new Date().getTime() / 1000); + if (closedPoll) + EmbarkJS.Storage.get(web3.utils.toAscii(closedPoll._description)).then(content => { + closedPoll.content = JSON.parse(content); + this.setState({ closedPoll }); + this.props.replacePoll(closedPoll); + }); + } + }; + + componentDidUpdate(prevProps) { + if (this.props.polls !== prevProps.polls) { + this.loadLatestPolls(); + } + } + + render() { + const { openPoll, closedPoll } = this.state; + const { decimals } = this.props; + + if (openPoll) { + openPoll._tokenSum = 0; + openPoll._votesSum = 0; + for (let i = 0; i < openPoll._numBallots; i++) { + openPoll._tokenSum += parseInt(utils.fromTokenDecimals(openPoll._tokenTotal[i], decimals), 10); + openPoll._votesSum += parseInt(openPoll._quadraticVotes[i], 10); + } + } + + if (closedPoll) { + closedPoll._tokenSum = 0; + closedPoll._votesSum = 0; + for (let i = 0; i < closedPoll._numBallots; i++) { + closedPoll._tokenSum += parseInt(utils.fromTokenDecimals(closedPoll._tokenTotal[i], decimals), 10); + closedPoll._votesSum += parseInt(closedPoll._quadraticVotes[i], 10); + } + } + + return ( + +
+
+ + + Status {this.props.symbol} Voting + + Create a poll or vote in one. Your vote helps us decide our product and community direction. + +
+ + {openPoll && openPoll.content && ( +
+

Open Polls

+ + + + {openPoll.content.title} + + Closes: {new Date(openPoll._endTime * 1000).DDMMYYYY()} +

+ Voters: {openPoll._voters} +
+ Total votes: {openPoll._votesSum} +
+ Total {this.props.symbol}: {openPoll._tokenSum} +

+ + VOTE NOW + +
+
+ +
+ )} + + {closedPoll && closedPoll.content && ( +
+

Closed Polls

+ + + + {closedPoll.content.title} + + Closed: {new Date(closedPoll._endTime * 1000).DDMMYYYY()} +

+ Voters: {closedPoll._voters} +
+ Total votes: {closedPoll._votesSum} +
+ Total {this.props.symbol}: {closedPoll._tokenSum} +
+

+ + See results + +
+
+ +
+ )} +
+
+ ); + } +} + +export default withRouter(LandingPage); diff --git a/app/components/flow/LearnAboutBallots.js b/app/components/flow/LearnAboutBallots.js index 94da327..472d65c 100644 --- a/app/components/flow/LearnAboutBallots.js +++ b/app/components/flow/LearnAboutBallots.js @@ -1,6 +1,6 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; +import React, { Component, Fragment } from 'react'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CardContent from '@material-ui/core/CardContent'; @@ -29,82 +29,91 @@ class LearnAboutBallots extends Component { this.setState({ open: false }); }; - - componentDidUpdate(prevProps){ + componentDidUpdate(prevProps) { if (this.props.polls !== prevProps.polls && this.props.polls) { // TODO: see how to extract this. Maybe a higher order component? const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - if(poll && !poll.content){ + if (poll && !poll.content) { this.props.loadPollContent(poll); } } } - render(){ - const {polls, idPoll} = this.props; + render() { + const { polls, idPoll } = this.props; + + if (!polls) return null; - if(!polls) return null; - const poll = polls.find(p => p.idPoll == idPoll); - if(!poll || !poll.content) return null; + if (!poll || !poll.content) return null; const title = poll.content.title; const ballots = poll.content.ballots; - - return ( -
- {title} - - { - ballots.map((item, i) => { - return - - {item.title} + + return ( + +
+ {title} + + {ballots.map((item, i) => { + return ( + + + + {item.title} + {item.subtitle} - - - - - - }) - } -
-
- -
-
+
+ + + +
+ ); + })} +
+
+ + + +
+
); } } class BallotDialog extends Component { - handleClose = () => { this.props.onClose(this.props.selectedValue); }; - + handleListItemClick = value => { this.props.onClose(value); }; - + render() { const { onClose, title, text, polls, ...other } = this.props; - + return ( - - {title} - - {text} - - - - - + + {title} + + + {text} + + + + + + ); } } diff --git a/app/components/flow/OtherPolls.js b/app/components/flow/OtherPolls.js index 45e4b97..b995c82 100644 --- a/app/components/flow/OtherPolls.js +++ b/app/components/flow/OtherPolls.js @@ -1,133 +1,148 @@ import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; +import React, { Component, Fragment } from 'react'; import Typography from '@material-ui/core/Typography'; -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import utils from '../../utils/utils'; const pollsPerLoad = 3; - function pad(number, length) { - - var str = '' + number; - while (str.length < length) { - str = '0' + str; - } - - return str; - + var str = String(number); + while (str.length < length) { + str = '0' + str; } + return str; +} + // TODO: extract to utils -Date.prototype.DDMMYYYY = function () { - var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); - var dd = pad(this.getDate(), 2); - - return dd + '/' + MM + '/' + yyyy ; - }; +Date.prototype.DDMMYYYY = function() { + var yyyy = this.getFullYear().toString(); + var MM = pad(this.getMonth() + 1, 2); + var dd = pad(this.getDate(), 2); + + return dd + '/' + MM + '/' + yyyy; +}; class OtherPolls extends Component { + state = { + firstLoad: true + }; - state = { - firstLoad: true + loadIPFSpollContent = async () => { + let filterFn; + if (this.props.pollType == 'open') { + filterFn = x => !x._canceled && x._endTime > new Date().getTime() / 1000; + } else { + filterFn = x => !x._canceled && x._endTime < new Date().getTime() / 1000; + } + this.props.loadPollRange(filterFn, this.props.start, this.props.end); + }; + + loadMorePollsHandle = async () => { + let filterFn; + if (this.props.pollType == 'open') { + filterFn = x => !x._canceled && x._endTime > new Date().getTime() / 1000; + } else { + filterFn = x => !x._canceled && x._endTime < new Date().getTime() / 1000; } - loadIPFSpollContent = async () => { - let filterFn; - if(this.props.pollType == 'open'){ - filterFn = x => !x._canceled && x._endTime > (new Date()).getTime() / 1000; - } else { - filterFn = x => !x._canceled && x._endTime < (new Date()).getTime() / 1000; - } - this.props.loadPollRange(filterFn, this.props.start, this.props.end); - } - - loadMorePollsHandle = async () => { - let filterFn; - if(this.props.pollType == 'open'){ - filterFn = x => !x._canceled && x._endTime > (new Date()).getTime() / 1000; - } else { - filterFn = x => !x._canceled && x._endTime < (new Date()).getTime() / 1000; - } + this.props.loadMorePolls(filterFn); + }; - this.props.loadMorePolls(filterFn); + componentWillMount() { + if (this.state.firstLoad) { + this.setState({ firstLoad: false }); + this.loadIPFSpollContent(); + } + } + + render() { + let { pollType, polls } = this.props; + if (!polls) { + return null; } + if (!pollType) pollType = 'open'; - - componentWillMount(){ - if(this.state.firstLoad){ - this.setState({firstLoad: false}); - this.loadIPFSpollContent(); - } + if (polls && polls.length) { + if (pollType == 'open') { + polls = polls.filter(x => !x._canceled && x._endTime > new Date().getTime() / 1000); + } else { + polls = polls.filter(x => !x._canceled && x._endTime < new Date().getTime() / 1000); + } } - render() { - let {pollType, polls} = this.props; - if(!polls){ - return null; - } + return ( + +
+ + {pollType == 'open' ? 'Open polls' : 'Closed polls'} ({polls.length}) + + {polls.map((p, i) => { + if (i >= this.props.end) return null; + if (p._canceled) return null; - if(!pollType) pollType = 'open'; - - if(polls && polls.length){ - if(pollType == 'open'){ - polls = polls.filter(x => !x._canceled && x._endTime > (new Date()).getTime() / 1000); - } else { - polls = polls.filter(x => !x._canceled && x._endTime < (new Date()).getTime() / 1000); + p._tokenSum = 0; + p._votesSum = 0; + for (let i = 0; i < p._numBallots; i++) { + p._tokenSum += parseInt(utils.fromTokenDecimals(p._tokenTotal[i], this.props.decimals), 10); + p._votesSum += parseInt(p._quadraticVotes[i], 10); } - } + if (p.content) { + return ( + + + + {p.content.title} + + + + {pollType == 'open' ? 'Closes: ' : 'Closed: '} {new Date(p._endTime * 1000).DDMMYYYY()} + +

+ Voters: {p._voters} +
+ Total votes: {p._votesSum} +
+ Total {this.props.symbol}: {p._tokenSum} +

+ {pollType == 'open' && ( + + VOTE NOW + + )} + {pollType != 'open' && ( + + See results + + )} +
+
+ ); + } + return ( + + + + + + ); + })} - return -
- {pollType == 'open' ? 'Open polls' : 'Closed polls'} ({polls.length}) - { - polls.map((p, i) => { - - if(i >= this.props.end) return null; - if(p._canceled) return null; - - p._tokenSum = 0; - p._votesSum = 0; - for(let i = 0; i < p._numBallots; i++){ - p._tokenSum += parseInt(utils.fromTokenDecimals(p._tokenTotal[i], this.props.decimals), 10); - p._votesSum += parseInt(p._quadraticVotes[i], 10); - } - if(p.content){ - return - - {p.content.title} - - {pollType == "open" ? "Closes: " : "Closed: "} {new Date(p._endTime * 1000).DDMMYYYY()} -

- Voters: {p._voters}
- Total votes: {p._votesSum}
- Total {this.props.symbol}: {p._tokenSum}

- { pollType == 'open' && VOTE NOW } - { pollType != 'open' && See results } - -
-
- } else { - return - - - - - } - }) - } - -
- { polls && polls.length > this.props.end && - Show more polls } -
-
-
; - } +
+ {polls && polls.length > this.props.end && ( + + Show more polls + + )} +
+
+
+ ); + } } export default OtherPolls; diff --git a/app/components/flow/PollVoting.js b/app/components/flow/PollVoting.js index 8f19acb..71974fc 100644 --- a/app/components/flow/PollVoting.js +++ b/app/components/flow/PollVoting.js @@ -1,75 +1,72 @@ import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; import { withStyles } from '@material-ui/core/styles'; import Slider from '@material-ui/lab/Slider'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; -import { withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom'; import utils from '../../utils/utils'; const styles = { card: { display: 'flex', flexDirection: 'column', - alignItems: 'center', + alignItems: 'center' }, thumb: { width: '24px', height: '24px' }, appBar: { - position: 'relative', + position: 'relative' }, flex: { - flex: 1, - }, + flex: 1 + } }; const arraysEqual = (arr1, arr2) => { - if(arr1.length !== arr2.length) - return false; - for(var i = arr1.length; i--;) { - if(arr1[i] !== arr2[i]) - return false; + if (arr1.length !== arr2.length) return false; + for (var i = arr1.length; i--; ) { + if (arr1[i] !== arr2[i]) return false; } return true; -} +}; -const shuffleArray = (array) => { +const shuffleArray = array => { for (let i = array.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [array[i], array[j]] = [array[j], array[i]]; // eslint-disable-line no-param-reassign + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; // eslint-disable-line no-param-reassign } -} +}; class PollVoting extends Component { - state = { votes: [], originalVotes: [], voteOrder: [], t: new Date() - } + }; - componentDidMount(){ - const {polls, originalVotes, idPoll, history} = this.props; + componentDidMount() { + const { polls, originalVotes, idPoll, history } = this.props; - if(!polls){ + if (!polls) { history.push('/'); return; } const poll = polls.find(p => p.idPoll == idPoll); - if(!poll){ + if (!poll) { history.push('/'); return; } const votes = []; const voteOrder = []; - if(originalVotes.length){ - for(let i = 0; i < poll._numBallots; i++){ + if (originalVotes.length) { + for (let i = 0; i < poll._numBallots; i++) { votes[i] = originalVotes[i]; voteOrder.push(i); } @@ -87,89 +84,105 @@ class PollVoting extends Component { updateVotes = i => numVotes => { const votes = this.state.votes; votes[i] = numVotes; - this.setState({votes, t: new Date()}); - } + this.setState({ votes, t: new Date() }); + }; sendToReview = () => { - - const seconds = this.props.polls.find(p => p.idPoll == this.props.idPoll)._endTime - (new Date()).getTime() / 1000; - if(seconds <= 0){ - alert("Poll is expired"); + const seconds = this.props.polls.find(p => p.idPoll == this.props.idPoll)._endTime - new Date().getTime() / 1000; + if (seconds <= 0) { + alert('Poll is expired'); this.props.history.push('/'); } else { this.props.setVotesToReview(this.state.votes); this.props.history.push('/review/' + this.props.idPoll); } - } + }; - render(){ - const {polls, classes, balances, idPoll, back, decimals} = this.props; - const {originalVotes, votes, voteOrder} = this.state; - const {fromWei} = web3.utils; + render() { + const { polls, classes, balances, idPoll, back, decimals } = this.props; + const { originalVotes, votes, voteOrder } = this.state; + const { fromWei } = web3.utils; - if(!polls){ + if (!polls) { return null; } const symbol = this.props.symbol; const poll = polls.find(p => p.idPoll == idPoll); - if(!poll) return null; - + if (!poll) return null; + const title = poll.content.title; - const ballots = poll.content.ballots + const ballots = poll.content.ballots; const balance = utils.fromTokenDecimals(balances[idPoll].tokenBalance, decimals); const cantVote = balance == 0 || !poll._canVote; const availableCredits = parseInt(balance, 10) - votes.reduce((prev, curr) => prev + curr * curr, 0); - const disableVote = cantVote || votes.reduce((x,y) => x+y, 0) == 0; + const disableVote = cantVote || votes.reduce((x, y) => x + y, 0) == 0; // Votes calculation - const originalVotesQty = originalVotes.reduce((x,y) => x+y, 0); + const originalVotesQty = originalVotes.reduce((x, y) => x + y, 0); // Calculating votes availables const maxVotes = Math.floor(Math.sqrt(balance)); const maxValuesForBallots = []; let votedTokens = 0; - for(let i = 0; i < poll._numBallots; i++){ - if(votes[i] == undefined){ + for (let i = 0; i < poll._numBallots; i++) { + if (votes[i] == undefined) { votes[i] = 0; } else { - votedTokens += votes[i]*votes[i]; + votedTokens += votes[i] * votes[i]; } } - - for(let i = 0; i < poll._numBallots; i++){ - maxValuesForBallots[i] = Math.floor(Math.sqrt(balance - votedTokens + votes[i]*votes[i])); + + for (let i = 0; i < poll._numBallots; i++) { + maxValuesForBallots[i] = Math.floor(Math.sqrt(balance - votedTokens + votes[i] * votes[i])); } - return -
- {title} - { voteOrder.map((v, i) => { - const item = ballots[v]; - return - - })} -
-
- {availableCredits} Credits left - -
-
+ return ( + +
+ {title} + {voteOrder.map((v, i) => { + const item = ballots[v]; + return ( + + ); + })} +
+
+ + {availableCredits} Credits left + + +
+
+ ); } } - class BallotSlider extends Component { - state = { value: 0, interval: null - } + }; - componentDidMount(){ - this.setState({value: this.props.votes || 0}); + componentDidMount() { + this.setState({ value: this.props.votes || 0 }); } /* @@ -181,95 +194,109 @@ class BallotSlider extends Component { this.props.updateVotes(value); };*/ - - - - increaseVotes = (event) => { + increaseVotes = event => { this.removeInterval(); const updateVotes = () => { let value = this.state.value; - if(value + 1 > this.props.maxVotesAvailable){ + if (value + 1 > this.props.maxVotesAvailable) { value = this.props.maxVotesAvailable; } else { value++; } - this.setState({value}); + this.setState({ value }); this.props.updateVotes(value); }; updateVotes(); const interval = setInterval(updateVotes, 150); - this.setState({interval}); - } + this.setState({ interval }); + }; - reduceVotes = (event) => { + reduceVotes = event => { this.removeInterval(); const updateVotes = () => { let value = this.state.value; - if(value - 1 < 0){ + if (value - 1 < 0) { value = 0; - } else { + } else { value--; } - this.setState({value}); + this.setState({ value }); this.props.updateVotes(value); - }; updateVotes(); const interval = setInterval(updateVotes, 150); - this.setState({interval}); - } + this.setState({ interval }); + }; removeInterval = () => { clearInterval(this.state.interval); - this.setState({interval: null}); + this.setState({ interval: null }); + }; - } - - render(){ - const {maxVotes, maxVotesAvailable, classes, cantVote, balance, symbol, title, subtitle} = this.props; - const {value} = this.state; + render() { + const { maxVotes, maxVotesAvailable, classes, cantVote, balance, symbol, title, subtitle } = this.props; + const { value } = this.state; const nextVote = value + 1; const toBN = web3.utils.toBN; - let percentage = Math.round(value * 100 / maxVotes); - percentage = percentage > 100 ? 100 : percentage; + let percentage = Math.round((value * 100) / maxVotes); + percentage = percentage > 100 ? 100 : percentage; - return - - {title} - {subtitle} -
-
- -
-
- -
-
-
- - {value} votes
{value*value} Credits
-
-
-
-
+ return ( + + + + {title} + + {subtitle} +
+
+ +
+
+ +
+
+
+ + + + {value} votes
+ {value * value} Credits +
+
+
- - ; +
+
+
+ + + ); } } - // // {balance > 0 && !cantVote && Your votes: {value} ({value * value} {symbol})} // { nextVote <= maxVotesAvailable && !cantVote ? - Additional vote will cost {nextVote*nextVote - value*value} {symbol} : (balance > 0 && !cantVote && - Not enough balance available to buy additional votes) } - - - export default withRouter(withStyles(styles)(PollVoting)); diff --git a/app/components/flow/Results.js b/app/components/flow/Results.js index 6d2c176..532e70f 100644 --- a/app/components/flow/Results.js +++ b/app/components/flow/Results.js @@ -1,184 +1,230 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; import PollManager from 'Embark/contracts/PollManager'; import utils from '../../utils/utils'; class Results extends Component { - state = { isError: false, poll: null, isPending: true, netId: 3 + }; - } - - constructor(props){ + constructor(props) { super(props); - if(props.polls) - this.state.poll = props.polls.find(p => p.idPoll == props.idPoll); + if (props.polls) this.state.poll = props.polls.find(p => p.idPoll == props.idPoll); } - - componentDidUpdate(prevProps){ + componentDidUpdate(prevProps) { if (this.props.idPoll !== prevProps.idPoll) { this.updatePoll(); } - if(this.props.polls !== prevProps.polls){ + if (this.props.polls !== prevProps.polls) { const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - if(poll && !poll.content){ + if (poll && !poll.content) { this.props.loadPollContent(poll); } } } - updatePoll(){ - const idPoll = this.props.idPoll; + updatePoll() { + const idPoll = this.props.idPoll; - PollManager.methods.poll(idPoll).call().then(poll => { - this.setState({poll}); - }) + PollManager.methods + .poll(idPoll) + .call() + .then(poll => { + this.setState({ poll }); + }); } - componentDidMount(){ - const {transaction, idPoll, transactionHash} = this.props; + componentDidMount() { + const { transaction, idPoll, transactionHash } = this.props; EmbarkJS.onReady(() => { this.updatePoll(); web3.eth.net.getId((err, netId) => { - this.setState({netId}); + this.setState({ netId }); }); - if(transaction[idPoll]){ - transaction[idPoll].catch(x => { - this.setState({isError: true}); - }).then(() => { - this.updatePoll(); - }) + if (transaction[idPoll]) { + transaction[idPoll] + .catch(error => { + this.setState({ isError: true }); + }) + .then(() => { + this.updatePoll(); + }); let req = false; let interval = setInterval(async () => { - if(req || !transactionHash[idPoll]) return; + if (req || !transactionHash[idPoll]) return; req = true; try { const receipt = await web3.eth.getTransactionReceipt(transactionHash[idPoll]); - if(receipt){ + if (receipt) { clearInterval(interval); - - if(receipt.status || receipt.status == "0x1"){ - this.setState({isPending: false}); + + if (receipt.status || receipt.status == '0x1') { + this.setState({ isPending: false }); this.updatePoll(); } else { - this.setState({isError: true}); + this.setState({ isError: true }); } } - } catch(e){ - } + } catch (error) {} req = false; }, 100); - } }); - } - render(){ - const {polls, idPoll, transaction, transactionHash} = this.props; - let {isError, poll, isPending, netId} = this.state; - if(!poll || !poll){ + render() { + const { polls, idPoll, transaction, transactionHash } = this.props; + let { isError, poll, isPending, netId } = this.state; + if (!poll || !poll) { return null; } const p = polls.find(p => p.idPoll == idPoll); - if(!p || !p.content) return null; + if (!p || !p.content) return null; const title = p.content.title; const ballots = p.content.ballots; const totalVotes = poll._quadraticVotes.map(x => parseInt(x, 10)).reduce((x, y) => x + y, 0); - const etherscanURL = netId == 3 ? 'https://ropsten.etherscan.io/tx/' : ( netId == 1 ? "https://etherscan.io/tx/" : ''); + const etherscanURL = netId == 3 ? 'https://ropsten.etherscan.io/tx/' : netId == 1 ? 'https://etherscan.io/tx/' : ''; - return - { isError &&
-
- Transaction failed - Your transaction failed to be written to the blockchain. This is usually because of network congestion. Please try again - - - -
} - - { !isError && transaction[idPoll] &&
- { isPending &&
-
-
-
-
+ return ( + + {isError && ( +
+
+ +
+ Transaction failed + + Your transaction failed to be written to the blockchain. This is usually because of network congestion. + Please try again + + + +
- Your vote will be posted once the transaction is complete. - Your vote is in the process of being confirmed in the blockchain + )} + + {!isError && transaction[idPoll] && ( +
+ {isPending && ( +
+
+
+
+
+
+ Your vote will be posted once the transaction is complete. + + Your vote is in the process of being confirmed in the blockchain + +
+ )} + {!isPending && transaction[idPoll] && ( +
+ + + Transaction confirmed! +
+ Your vote was posted. +
+
+ )} + {transactionHash[idPoll] && etherscanURL && ( + + + View details on Etherscan + + + )} +
+ )} +
+ {!isError && ( + + + {title} + + {ballots.map((item, i) => ( + + ))} + + )}
- } - { !isPending && transaction[idPoll] &&
- - Transaction confirmed!
- Your vote was posted.
-
} - { transactionHash[idPoll] && etherscanURL && View details on Etherscan } -
- } -
- { !isError && - {title} - { ballots.map((item, i) => ) } - - } -
- ; + + ); } } - class BallotResult extends Component { - state = { show: false - } + }; showDetails = () => { const show = this.state.show; - this.setState({show: !show}); - } + this.setState({ show: !show }); + }; - render(){ - const {title, quadraticVotes, tokenTotal, totalVotes, totalVoters, decimals} = this.props; - const {show} = this.state; + render() { + const { title, quadraticVotes, tokenTotal, totalVotes, totalVoters, decimals } = this.props; + const { show } = this.state; - const votePercentage = totalVotes > 0 ? parseInt(quadraticVotes) / totalVotes * 100 : 0; + const votePercentage = totalVotes > 0 ? (parseInt(quadraticVotes) / totalVotes) * 100 : 0; const totalInUnits = utils.fromTokenDecimals(tokenTotal, decimals); - - - return ( - {title} -
-
- + return ( + + + {title} + +
+
+ +
+ {votePercentage.toFixed(2)}%
- {votePercentage.toFixed(2)}% -
- {show &&
    - Voters: {totalVoters} - Total votes: {quadraticVotes} - Total {this.props.symbol}: {totalInUnits} -
} - ); + {show && ( +
    + + Voters: {totalVoters} + + + Total votes: {quadraticVotes} + + + Total {this.props.symbol}: {totalInUnits} + +
+ )} + + ); } } diff --git a/app/components/flow/ReviewVotes.js b/app/components/flow/ReviewVotes.js index 74d4916..eee0343 100644 --- a/app/components/flow/ReviewVotes.js +++ b/app/components/flow/ReviewVotes.js @@ -1,30 +1,28 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import PollManager from 'Embark/contracts/PollManager'; -import { withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom'; import utils from '../../utils/utils'; class ReviewVotes extends Component { - state = { isSubmitting: false - } + }; vote = () => { - this.setState({isSubmitting: true}); + this.setState({ isSubmitting: true }); const { vote, unvote } = PollManager.methods; - const { votes, history, idPoll, decimals} = this.props; + const { votes, history, idPoll, decimals } = this.props; const { toWei, toBN } = web3.utils; - - const seconds = this.props.polls.find(p => p.idPoll == this.props.idPoll)._endTime - (new Date()).getTime() / 1000; - if(seconds <= 0){ - alert("Poll is expired"); + const seconds = this.props.polls.find(p => p.idPoll == this.props.idPoll)._endTime - new Date().getTime() / 1000; + if (seconds <= 0) { + alert('Poll is expired'); this.props.history.push('/'); return; } @@ -35,94 +33,105 @@ class ReviewVotes extends Component { return utils.toTokenDecimals(num.toString(), decimals); }); - const balance4Voting = ballots.reduce((prev, curr) => toBN(prev).add(toBN(curr)), toBN("0")); + const balance4Voting = ballots.reduce((prev, curr) => toBN(prev).add(toBN(curr)), toBN('0')); const toSend = balance4Voting == 0 ? unvote(idPoll) : vote(idPoll, ballots.map(x => x.toString())); - toSend.estimateGas() - .then(gasEstimated => { - console.log("voting gas estimated: " + gasEstimated); + toSend.estimateGas().then(gasEstimated => { + console.log('voting gas estimated: ' + gasEstimated); - const transaction = toSend.send({gas: gasEstimated + 100000}); - - transaction.on('transactionHash', hash => { - this.props.setTransactionHash(idPoll, hash); - this.props.setTransactionPromise(idPoll, transaction); - history.push('/results/' + idPoll); - }); - - transaction.catch(err => { - this.setState({isSubmitting: false}); - }) - + const transaction = toSend.send({ gas: gasEstimated + 100000 }); + transaction.on('transactionHash', hash => { + this.props.setTransactionHash(idPoll, hash); + this.props.setTransactionPromise(idPoll, transaction); + history.push('/results/' + idPoll); }); - } - componentDidMount(){ - const {polls, originalVotes, idPoll, history} = this.props; + transaction.catch(error => { + this.setState({ isSubmitting: false }); + }); + }); + }; - if(!polls){ + componentDidMount() { + const { polls, originalVotes, idPoll, history } = this.props; + + if (!polls) { history.push('/'); return; } const poll = polls.find(p => p.idPoll == idPoll); - if(!poll) { + if (!poll) { history.push('/'); return; - }; + } } - render(){ - const {polls, balances, votes, idPoll, decimals} = this.props; - const {isSubmitting} = this.state; - const {fromWei} = web3.utils; + render() { + const { polls, balances, votes, idPoll, decimals } = this.props; + const { isSubmitting } = this.state; + const { fromWei } = web3.utils; - if(!polls|| !balances[idPoll]){ + if (!polls || !balances[idPoll]) { return null; } - const poll = polls.find(p => p.idPoll == idPoll);; - if(!poll) return null; - - const ballots = poll.content.ballots + const poll = polls.find(p => p.idPoll == idPoll); + if (!poll) return null; + + const ballots = poll.content.ballots; const balance = utils.fromTokenDecimals(balances[idPoll].tokenBalance, decimals); const availableCredits = parseInt(balance, 10) - votes.reduce((prev, curr) => prev + curr * curr, 0); - - return (polls ?
- Review your vote - { ballots.map((item, i) => { - return votes[i] > 0 ? + return polls ? ( + +
+ Review your vote + + {ballots.map((item, i) => { + return votes[i] > 0 ? ( + + + + {item.title} + + {item.subtitle} +
+
+ {votes[i]} + votes +
+
+ {votes[i] * votes[i]} + credits +
+
+
+
+ ) : null; + })} + + - {item.title} - {item.subtitle} -
-
- {votes[i]} - votes -
-
- {votes[i] * votes[i]} - credits -
-
+ + Unused voting power + + + {availableCredits} credits + + Add votes
-
: null; - })} - - - - Unused voting power - {availableCredits} credits - Add votes - - -
-
- -
: null); +
+
+
+ +
+
+ ) : null; } } diff --git a/app/components/flow/TitleScreen.js b/app/components/flow/TitleScreen.js index 128d9ef..8af7e66 100644 --- a/app/components/flow/TitleScreen.js +++ b/app/components/flow/TitleScreen.js @@ -1,25 +1,24 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; const pad = (n, width, z) => { z = z || '0'; - n = n + ''; + n = String(n); return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; -} +}; class TitleScreen extends Component { - state = { time: {}, seconds: -1, initTimer: false - } + }; - timer = 0 + timer = 0; - secondsToTime(secs){ + secondsToTime(secs) { let days = Math.floor(secs / 86400); let divisor_for_hours = secs % 86400; let hours = Math.floor(divisor_for_hours / (60 * 60)); @@ -27,9 +26,9 @@ class TitleScreen extends Component { let minutes = Math.floor(divisor_for_minutes / 60); let obj = { - "d": days, - "h": hours, - "m": minutes + d: days, + h: hours, + m: minutes }; return obj; @@ -45,111 +44,141 @@ class TitleScreen extends Component { let seconds = this.state.seconds - 1; this.setState({ time: this.secondsToTime(seconds), - seconds: seconds, + seconds: seconds }); - if (seconds == 0) { + if (seconds == 0) { clearInterval(this.timer); } } - componentWillUnmount(){ + componentWillUnmount() { clearInterval(this.timer); } - componentDidMount(){ - if(this.props.polls){ + componentDidMount() { + if (this.props.polls) { this.initTimer(); } } - componentDidUpdate(prevProps){ + componentDidUpdate(prevProps) { if (this.props.polls !== prevProps.polls && this.props.polls) { this.initTimer(); // TODO: see how to extract this. Maybe a higher order component? const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - if(poll && !poll.content){ + if (poll && !poll.content) { this.props.loadPollContent(poll); } } } - initTimer(){ - if(!this.props.polls || !this.props.polls.length) return; + initTimer() { + if (!this.props.polls || !this.props.polls.length) return; - if(this.state.initTimer) return; + if (this.state.initTimer) return; - this.setState({initTimer: true}); + this.setState({ initTimer: true }); const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - const seconds = poll._endTime - (new Date()).getTime() / 1000 - if(seconds > 0){ + const seconds = poll._endTime - new Date().getTime() / 1000; + if (seconds > 0) { let timeLeftVar = this.secondsToTime(seconds); this.setState({ time: timeLeftVar, seconds }); this.startTimer(); } else { - this.setState({seconds}); + this.setState({ seconds }); } } - render(){ - const {time, seconds} = this.state; - const {polls, idPoll} = this.props; + render() { + const { time, seconds } = this.state; + const { polls, idPoll } = this.props; + + if (!polls || !polls.length) return null; - if(!polls || !polls.length) return null; - const poll = polls.find(p => p.idPoll == idPoll); - if(!poll) return null; + if (!poll) return null; - if(!poll.content) return null; + if (!poll.content) return null; const title = poll.content.title; const description = poll.content.description; const canceled = poll._canceled; - - return -
- {!canceled &&
-
- - {title} - -
-
- { seconds > 0 &&
- Voting ends in -
    -
  • - {pad(time.d, 2)} - Days -
  • -
  • - {pad(time.h, 2)} - Hours -
  • -
  • - {pad(time.m, 2)} - Mins -
  • -
-
-
-

See ongoing results

+ return ( + +
+ {!canceled && ( +
+
+ + {title} + +
+
+ {seconds > 0 && ( +
+ Voting ends in +
    +
  • + {pad(time.d, 2)} + + Days + +
  • +
  • + {pad(time.h, 2)} + + Hours + +
  • +
  • + {pad(time.m, 2)} + + Mins + +
  • +
+
+ + + +
+

+ See ongoing results +

+
+
+ )} + {seconds < 0 && ( +
+ Poll closed + + The vote was finished {parseInt(Math.abs(seconds) / 86400, 10)} day(s) ago + +
+ + + +
+
+ )} +
+ )}
-
} - { seconds < 0 &&
- Poll closed - The vote was finished {parseInt(Math.abs(seconds) / 86400, 10)} day(s) ago -
- -
-
} -
} -
- - ; + + ); } } diff --git a/app/components/flow/VotingCredits.js b/app/components/flow/VotingCredits.js index 6028525..d5b5e9f 100644 --- a/app/components/flow/VotingCredits.js +++ b/app/components/flow/VotingCredits.js @@ -1,34 +1,32 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; -import { withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom'; import HelpDialog from './HelpDialog'; import utils from '../../utils/utils'; - -Date.prototype.DDMMYYYY = function () { +Date.prototype.DDMMYYYY = function() { var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); + var MM = pad(this.getMonth() + 1, 2); var dd = pad(this.getDate(), 2); - return dd + '/' + MM + '/' + yyyy ; + return dd + '/' + MM + '/' + yyyy; }; function pad(number, length) { - var str = '' + number; + var str = String(number); while (str.length < length) { - str = '0' + str; + str = '0' + str; } return str; } class VotingCredits extends Component { - state = { - open: false, + open: false }; handleClickOpen = () => { @@ -39,18 +37,18 @@ class VotingCredits extends Component { this.setState({ open: false }); }; - componentDidMount(){ - const {polls, balances, history} = this.props; - if(!polls || !balances || !balances.length){ + componentDidMount() { + const { polls, balances, history } = this.props; + if (!polls || !balances || !balances.length) { history.push('/'); } } - componentDidUpdate(prevProps){ + componentDidUpdate(prevProps) { if (this.props.polls !== prevProps.polls && this.props.polls) { // TODO: see how to extract this. Maybe a higher order component? const poll = this.props.polls.find(p => p.idPoll == this.props.idPoll); - if(poll && !poll.content){ + if (poll && !poll.content) { this.props.loadPollContent(poll); } } @@ -58,73 +56,91 @@ class VotingCredits extends Component { redirectToConnect = () => { this.props.history.push('/wallet/' + this.props.idPoll); - } + }; - render(){ - const {polls, balances, idPoll, decimals} = this.props; + render() { + const { polls, balances, idPoll, decimals } = this.props; - if(!polls || !balances) return null; + if (!polls || !balances) return null; const poll = polls.find(p => p.idPoll == idPoll); - if(!poll || !poll.content) return null; - + if (!poll || !poll.content) return null; + let title = poll.content.title; let description = poll.content.description; - let ethBalance = web3.utils.fromWei(balances[idPoll].ethBalance, "ether"); + let ethBalance = web3.utils.fromWei(balances[idPoll].ethBalance, 'ether'); let tokenBalance = Math.floor(utils.fromTokenDecimals(balances[idPoll].tokenBalance, decimals)); - - const d = new Date(poll.blockInfo.timestamp * 1000); + const d = new Date(poll.blockInfo.timestamp * 1000); - return (polls ?
- {title} - - - - - Voting Credits - {tokenBalance} - - { tokenBalance >= 1 && - - You get one credit for each {this.props.symbol} held in your wallet at the time of poll was created ({d.DDMMYYYY()}). They are usable only in this poll. - } - { tokenBalance < 1 && -
- - No {this.props.symbol} in your wallet - - - To vote, you need to connect with a wallet that holds {this.props.symbol} tokens when the poll was created ({d.DDMMYYYY()}). - -
- } -
-
- { ethBalance == 0 && - - - ETH - {ethBalance} - -
- - Not enough ETH in your wallet + return polls ? ( + +
+ {title} + + + + + Voting Credits + {tokenBalance} - - You will sign a transaction to confirm your vote. No tokens are sent, but you need ETH to pay for gas (Ethereum network fee). - -
- - } -
-
- { (ethBalance == 0 || tokenBalance == 0) && } - { (ethBalance > 0 && tokenBalance > 0) && } -
-

Need help? Chat with us

- - : null); + {tokenBalance >= 1 && ( + + You get one credit for each {this.props.symbol} held in your wallet{' '} + at the time of poll was created ({d.DDMMYYYY()}). They are usable only in this poll. + + )} + {tokenBalance < 1 && ( +
+ + No {this.props.symbol} in your wallet + + + To vote, you need to connect with a wallet that holds {this.props.symbol} tokens{' '} + when the poll was created ({d.DDMMYYYY()}). + +
+ )} +
+
+ {ethBalance == 0 && ( + + + + ETH + {ethBalance} + +
+ + Not enough ETH in your wallet + + + You will sign a transaction to confirm your vote. No tokens are sent, but you need ETH to pay for + gas (Ethereum network fee). + +
+
+
+ )} +
+
+ {(ethBalance == 0 || tokenBalance == 0) && ( + + + + )} + {ethBalance > 0 && tokenBalance > 0 && ( + + + + )} +
+

+ Need help? Chat with us +

+ +
+ ) : null; } } diff --git a/app/components/flow/create/PollCreationCredits.js b/app/components/flow/create/PollCreationCredits.js index d3b56f6..40fd396 100644 --- a/app/components/flow/create/PollCreationCredits.js +++ b/app/components/flow/create/PollCreationCredits.js @@ -1,32 +1,31 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import Typography from '@material-ui/core/Typography'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; -import { withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom'; import HelpDialog from '../HelpDialog'; -import DappToken from 'Embark/contracts/DappToken'; +import DappToken from 'Embark/contracts/DappToken'; import utils from '../../../utils/utils'; -Date.prototype.DDMMYYYY = function () { +Date.prototype.DDMMYYYY = function() { var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); + var MM = pad(this.getMonth() + 1, 2); var dd = pad(this.getDate(), 2); - return dd + '/' + MM + '/' + yyyy ; + return dd + '/' + MM + '/' + yyyy; }; function pad(number, length) { - var str = '' + number; + var str = String(number); while (str.length < length) { - str = '0' + str; + str = '0' + str; } return str; } class PollCreationCredits extends Component { - state = { open: false, tokenBalance: '-', @@ -41,84 +40,95 @@ class PollCreationCredits extends Component { this.setState({ open: false }); }; - redirectToConnect = () => { this.props.history.push('/wallet/poll-creation'); - } + }; - componentDidMount(){ - const {history, decimals} = this.props; + componentDidMount() { + const { history, decimals } = this.props; - if(this.props.poll.title !== undefined){ + if (this.props.poll.title !== undefined) { this.props.resetPoll(); history.push('/'); return; } EmbarkJS.onReady(async () => { - const tokenBalance = await DappToken.methods.balanceOf(web3.eth.defaultAccount).call({from: web3.eth.defaultAccount}); + const tokenBalance = await DappToken.methods + .balanceOf(web3.eth.defaultAccount) + .call({ from: web3.eth.defaultAccount }); const ethBalance = await web3.eth.getBalance(web3.eth.defaultAccount); - this.setState({tokenBalance, ethBalance}); + this.setState({ tokenBalance, ethBalance }); - if(web3.utils.fromWei(ethBalance.toString(), "ether") > 0 && + if ( + web3.utils.fromWei(ethBalance.toString(), 'ether') > 0 && Math.floor(utils.fromTokenDecimals(tokenBalance.toString(), decimals)) >= 1 - ){ + ) { history.push('/poll/title'); return; } - - }) + }); } - render(){ - let ethBalance = web3.utils.fromWei(this.state.ethBalance, "ether"); - let tokenBalance = this.state.tokenBalance != "-" ? Math.floor(utils.fromTokenDecimals(this.state.tokenBalance, this.props.decimals)) : "-"; + render() { + let ethBalance = web3.utils.fromWei(this.state.ethBalance, 'ether'); + let tokenBalance = + this.state.tokenBalance != '-' + ? Math.floor(utils.fromTokenDecimals(this.state.tokenBalance, this.props.decimals)) + : '-'; - if(this.state.tokenBalance === "-") return null; + if (this.state.tokenBalance === '-') return null; - return
- Create a Poll - - - - Voting Credits - {tokenBalance} - - { tokenBalance == 0 && -
- - No {this.props.symbol} in your wallet - - - To create a poll, you need to connect with a wallet that holds {this.props.symbol} tokens. - -
- } -
-
- { ethBalance == 0 && - - - ETH - {ethBalance} - -
- - Not enough ETH in your wallet + return ( + +
+ Create a Poll + + + + Voting Credits + {tokenBalance} - - You will sign a transaction to publish the poll. You need ETH to pay for gas (Ethereum network fee). - -
- - } -
-
- { (ethBalance == 0 || tokenBalance == 0) && } -
-

Need help? Chat with us

- ; + {tokenBalance == 0 && ( +
+ No {this.props.symbol} in your wallet + + To create a poll, you need to connect with a wallet that holds {this.props.symbol} tokens. + +
+ )} +
+
+ {ethBalance == 0 && ( + + + + ETH + {ethBalance} + +
+ Not enough ETH in your wallet + + You will sign a transaction to publish the poll. You need ETH to pay for gas (Ethereum network fee). + +
+
+
+ )} +
+
+ {(ethBalance == 0 || tokenBalance == 0) && ( + + + + )} +
+

+ Need help? Chat with us +

+
+ ); } } diff --git a/app/components/flow/create/PollCreationResults.js b/app/components/flow/create/PollCreationResults.js index b4343f3..384a42d 100644 --- a/app/components/flow/create/PollCreationResults.js +++ b/app/components/flow/create/PollCreationResults.js @@ -1,160 +1,211 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' -import {Link} from "react-router-dom"; +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; +import { Link } from 'react-router-dom'; function pad(number, length) { - var str = '' + number; + var str = String(number); while (str.length < length) { - str = '0' + str; + str = '0' + str; } return str; } -Date.prototype.DDMMYYYYatHHMM = function () { - var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); - var dd = pad(this.getDate(), 2); - var hh = pad(this.getHours(), 2); - var mm = pad(this.getMinutes(), 2) - - return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); - }; +Date.prototype.DDMMYYYYatHHMM = function() { + var yyyy = this.getFullYear().toString(); + var MM = pad(this.getMonth() + 1, 2); + var dd = pad(this.getDate(), 2); + var hh = pad(this.getHours(), 2); + var mm = pad(this.getMinutes(), 2); + + return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); +}; class PollCreationResults extends Component { + state = { + poll: {}, + idPoll: null, + isError: false, + isPending: true, + netId: 3 + }; - state = { - poll: {}, - idPoll: null, - isError: false, - isPending: true, - netId: 3 + componentDidMount() { + const { pollTransaction, pollTransactionHash, history } = this.props; + + if (!pollTransaction || !pollTransactionHash) { + history.push('/'); + return; } - componentDidMount(){ - const {pollTransaction, pollTransactionHash, history} = this.props; + this.setState({ poll: Object.assign({}, this.props.poll) }); - if(!pollTransaction || !pollTransactionHash){ - history.push('/'); - return; - } + EmbarkJS.onReady(() => { + web3.eth.net.getId((err, netId) => { + this.setState({ netId }); + }); - this.setState({poll: Object.assign({}, this.props.poll)}); - - EmbarkJS.onReady(() => { - web3.eth.net.getId((err, netId) => { - this.setState({netId}); - }); - - if(pollTransaction){ - pollTransaction.catch(x => { - this.setState({isError: true}); - }); - - let req = false; - let interval = setInterval(async () => { - if(req || !pollTransactionHash) return; - - req = true; - const receipt = await web3.eth.getTransactionReceipt(pollTransactionHash); - if(receipt){ - clearInterval(interval); - - if(receipt.status || receipt.status == "0x1"){ - this.setState({isPending: false}); - - const ev = web3.eth.abi.decodeLog(PollManager.options.jsonInterface.find(x => x.name == "PollCreated").inputs, receipt.logs[0].data, receipt.logs[0].topics.slice(1)); - - await this.props.getPolls(); - const poll = await PollManager.methods.poll(ev.idPoll).call(); - this.props.loadPollContent(poll); - - this.props.resetPoll(); - - this.setState({idPoll: ev.idPoll}) - } else { - this.setState({isError: true}); - } - } - req = false; - }, 100); - } + if (pollTransaction) { + pollTransaction.catch(error => { + this.setState({ isError: true }); }); - } - linkTo = id => e => { - let url = window.location.href.replace(window.location.hash, ''); - url += '?d=' + (new Date()).getTime() + '#/titleScreen/' + id; + let req = false; + let interval = setInterval(async () => { + if (req || !pollTransactionHash) return; - window.location.href = url; - } + req = true; + const receipt = await web3.eth.getTransactionReceipt(pollTransactionHash); + if (receipt) { + clearInterval(interval); - render(){ - const {pollTransaction, pollTransactionHash} = this.props; - let {isError, isPending, netId, idPoll, poll} = this.state; + if (receipt.status || receipt.status == '0x1') { + this.setState({ isPending: false }); - const etherscanURL = netId == 3 ? 'https://ropsten.etherscan.io/tx/' : ( netId == 1 ? "https://etherscan.io/tx/" : ''); + const ev = web3.eth.abi.decodeLog( + PollManager.options.jsonInterface.find(x => x.name == 'PollCreated').inputs, + receipt.logs[0].data, + receipt.logs[0].topics.slice(1) + ); - if(poll.options == null) return null; + await this.props.getPolls(); + const poll = await PollManager.methods.poll(ev.idPoll).call(); + this.props.loadPollContent(poll); - return - - { isError &&
-
- Transaction failed - Your transaction failed to be written to the blockchain. This is usually because of network congestion. Please try again - - - -
} + this.props.resetPoll(); - { !isError && pollTransaction &&
- { isPending &&
-
-
-
-
-
- Your poll will be created once the transaction is complete - Your poll is in the process of being confirmed in the blockchain -
- } - { !isPending && pollTransaction &&
- - The poll was created and it’s now live! -
} - { pollTransactionHash && etherscanURL && View details on Etherscan } - - { idPoll !== null && See the poll } - - -
- } -
-
- {poll.title}

- {poll.description}


-
- Poll starts: - Today (upon publishing)

- Poll ends: - {poll.endDate.DDMMYYYYatHHMM()} -
- -

Options
- { - poll.options.map((item, i) => { - return
- {item.title} - {item.content} -
- }) + this.setState({ idPoll: ev.idPoll }); + } else { + this.setState({ isError: true }); + } } -
-
- -
; + req = false; + }, 100); } + }); + } + + linkTo = id => e => { + let url = window.location.href.replace(window.location.hash, ''); + url += '?d=' + new Date().getTime() + '#/titleScreen/' + id; + + window.location.href = url; + }; + + render() { + const { pollTransaction, pollTransactionHash } = this.props; + let { isError, isPending, netId, idPoll, poll } = this.state; + + const etherscanURL = netId == 3 ? 'https://ropsten.etherscan.io/tx/' : netId == 1 ? 'https://etherscan.io/tx/' : ''; + + if (poll.options == null) return null; + + return ( + + {isError && ( +
+
+ +
+ Transaction failed + + Your transaction failed to be written to the blockchain. This is usually because of network congestion. + Please try again + + + + +
+ )} + + {!isError && pollTransaction && ( +
+ {isPending && ( +
+
+
+
+
+
+ Your poll will be created once the transaction is complete + + Your poll is in the process of being confirmed in the blockchain + +
+ )} + {!isPending && pollTransaction && ( +
+ + The poll was created and it’s now live! +
+ )} + {pollTransactionHash && etherscanURL && ( + + + View details on Etherscan + + + )} + + {idPoll !== null && ( + + + See the poll + + + )} +
+ )} +
+
+ + {poll.title} +
+
+
+ + {poll.description} +
+
+
+
+
+ + Poll starts: + + + Today (upon publishing) +
+
+
+ + Poll ends: + + + {poll.endDate.DDMMYYYYatHHMM()} + +
+ + +
+
+ Options +
+ {poll.options.map((item, i) => { + return ( +
+ {item.title} + {item.content} +
+ ); + })} +
+
+ + ); + } } export default withRouter(PollCreationResults); diff --git a/app/components/flow/create/PollDescription.js b/app/components/flow/create/PollDescription.js index 10d190f..44f4360 100644 --- a/app/components/flow/create/PollDescription.js +++ b/app/components/flow/create/PollDescription.js @@ -1,80 +1,82 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import FormHelperText from '@material-ui/core/FormHelperText'; import LinearProgress from '@material-ui/core/LinearProgress'; - class PollDescription extends Component { + state = { + description: '', + error: '' + }; - state = { - description: '', - error: '' + componentDidMount() { + if (this.props.poll.description !== undefined) { + this.setState({ description: this.props.poll.description }); } - componentDidMount(){ - if(this.props.poll.description !== undefined){ - this.setState({description: this.props.poll.description}); - } - - if(!this.props.poll.title){ - const {history} = this.props; - history.push('/'); - } + if (!this.props.poll.title) { + const { history } = this.props; + history.push('/'); } + } - handleChange = (event) => { - this.setState({error: ''}); - if(event.target.value.length <= 500){ - this.props.assignToPoll({description: event.target.value}); - this.setState({description: event.target.value}); - } + handleChange = event => { + this.setState({ error: '' }); + if (event.target.value.length <= 500) { + this.props.assignToPoll({ description: event.target.value }); + this.setState({ description: event.target.value }); } + }; - continue = () => { - const {description} = this.state; - const {history} = this.props; + continue = () => { + const { description } = this.state; + const { history } = this.props; - if(description.trim() != ''){ - this.props.assignToPoll({description}); - history.push('/poll/options'); - } else { - this.setState({error: "Required"}) - } + if (description.trim() != '') { + this.props.assignToPoll({ description }); + history.push('/poll/options'); + } else { + this.setState({ error: 'Required' }); } + }; - render() { - return + render() { + return ( +
- Create a Poll -
+ Create a Poll +
-
- {this.state.error && {this.state.error}} - {this.state.description.length} of 500 +
+ {this.state.error && {this.state.error}} + {this.state.description.length} of 500
- +
-
; - } +
+ ); + } } export default withRouter(PollDescription); diff --git a/app/components/flow/create/PollOptions.js b/app/components/flow/create/PollOptions.js index 02aaed1..0b5b8ca 100644 --- a/app/components/flow/create/PollOptions.js +++ b/app/components/flow/create/PollOptions.js @@ -1,6 +1,6 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; import TextField from '@material-ui/core/TextField'; import FormHelperText from '@material-ui/core/FormHelperText'; import Button from '@material-ui/core/Button'; @@ -8,7 +8,7 @@ import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; -import {SortableContainer, SortableElement, arrayMove} from 'react-sortable-hoc'; +import { SortableContainer, SortableElement, arrayMove } from 'react-sortable-hoc'; import LinearProgress from '@material-ui/core/LinearProgress'; import Slide from '@material-ui/core/Slide'; @@ -16,14 +16,14 @@ function Transition(props) { return ; } -const SortableItem = SortableElement(({value, editOption}) => -
- {value.title} - {value.content} -
-); +const SortableItem = SortableElement(({ value, editOption }) => ( +
+ {value.title} + {value.content} +
+)); -const SortableList = SortableContainer(({items, removeOption, editOption}) => { +const SortableList = SortableContainer(({ items, removeOption, editOption }) => { return (
{items.map((value, index) => ( @@ -34,167 +34,200 @@ const SortableList = SortableContainer(({items, removeOption, editOption}) => { }); class PollOptions extends Component { + state = { + error: '', + open: false, + options: [], + optionTitle: '', + optionContent: '', + edit: null, + stickyBarClass: 'stickyBar' + }; - state = { - error: '', + onSortEnd = ({ oldIndex, newIndex }) => { + this.setState({ + options: arrayMove(this.state.options, oldIndex, newIndex) + }); + }; + + handleChange = name => event => { + this.setState({ error: '' }); + const state = {}; + state[name] = event.target.value; + this.setState(state); + }; + + handleClickOpen = () => { + this.setState({ open: true, stickyBarClass: '' }); + }; + + addOption = () => { + if (this.state.optionTitle.trim() == '') { + this.setState({ error: 'Required' }); + } else { + const options = this.state.options; + + if (this.state.edit !== null) { + options[this.state.edit] = { title: this.state.optionTitle, content: this.state.optionContent }; + } else { + options.push({ title: this.state.optionTitle, content: this.state.optionContent }); + } + this.props.assignToPoll({ options }); + + this.setState({ open: false, - options: [], + edit: null, optionTitle: '', optionContent: '', - edit: null, + error: '', stickyBarClass: 'stickyBar' + }); + } + }; + + handleClose = () => { + this.setState({ open: false, edit: null, optionContent: '', optionTitle: '', stickyBarClass: 'stickyBar' }); + }; + + removeOption = i => () => { + if (i != null) { + if (confirm('Are you sure you want to delete this option?')) { + this.state.options.splice(i, 1); + this.setState({ options: this.state.options }); + this.handleClose(); + } + } + }; + + editOption = i => () => { + const state = {}; + state.open = true; + state.optionContent = this.state.options[i].content; + state.optionTitle = this.state.options[i].title; + state.edit = i; + state.stickyBarClass = ''; + this.setState(state); + }; + + continue = () => { + const { options } = this.state; + const { history } = this.props; + + if (options.length != 0) { + this.props.assignToPoll({ options }); + history.push('/poll/schedule'); + } else { + this.setState({ error: 'Required' }); + } + }; + + componentDidMount() { + if (this.props.poll.options !== undefined) { + this.setState({ options: this.props.poll.options }); } - onSortEnd = ({oldIndex, newIndex}) => { - this.setState({ - options: arrayMove(this.state.options, oldIndex, newIndex), - }); - }; - - handleChange = name => event => { - this.setState({error: ''}); - const state = {}; - state[name] = event.target.value; - this.setState(state); + if (!this.props.poll.description) { + const { history } = this.props; + history.push('/'); } + } - handleClickOpen = () => { - this.setState({ open: true, stickyBarClass: '' }); - }; - - - addOption = () => { - if(this.state.optionTitle.trim() == ''){ - this.setState({error: 'Required'}); - } else { - const options = this.state.options; - - if(this.state.edit !== null){ - options[this.state.edit] = {title: this.state.optionTitle, content: this.state.optionContent}; - } else { - options.push({title: this.state.optionTitle, content: this.state.optionContent}); - } - this.props.assignToPoll({options}); - - this.setState({ open: false, edit: null, optionTitle: '', optionContent: '', error: '', stickyBarClass: 'stickyBar' }); - } - } - - handleClose = () => { - this.setState({ open: false, edit: null, optionContent: '', optionTitle: '', stickyBarClass: 'stickyBar' }); - } - - removeOption = i => () => { - if(i != null){ - if(confirm("Are you sure you want to delete this option?")){ - this.state.options.splice(i, 1); - this.setState({options: this.state.options}); - this.handleClose(); - } - } - } - - editOption = i => () => { - const state = {}; - state.open = true; - state.optionContent = this.state.options[i].content; - state.optionTitle = this.state.options[i].title; - state.edit = i; - state.stickyBarClass = ''; - this.setState(state); - } - - continue = () => { - const {options} = this.state; - const {history} = this.props; - - if(options.length != 0){ - this.props.assignToPoll({options}); - history.push('/poll/schedule'); - } else { - this.setState({error: "Required"}) - } - } - - componentDidMount(){ - if(this.props.poll.options !== undefined){ - this.setState({options: this.props.poll.options}); - } - - if(!this.props.poll.description){ - const {history} = this.props; - history.push('/'); - } - } - - render() { - return + render() { + return ( +
-
+
Create a Poll - Add options to the poll - Add option -
- - + + Add options to the poll + + + + Add option + +
+
- +
- - - { this.state.edit !== null && } - + )} + - - { this.state.edit !== null ? "Edit poll option" : "Add new poll option" } - - - {this.state.error && {this.state.error}} -
- -
-
+ + + {this.state.edit !== null ? 'Edit poll option' : 'Add new poll option'} + + + + {this.state.error && {this.state.error}} +
+ +
+
-
; - } +
+ ); + } } -export default (withRouter(PollOptions)); +export default withRouter(PollOptions); diff --git a/app/components/flow/create/PollReview.js b/app/components/flow/create/PollReview.js index e855d38..94210f6 100644 --- a/app/components/flow/create/PollReview.js +++ b/app/components/flow/create/PollReview.js @@ -1,110 +1,131 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; import Button from '@material-ui/core/Button'; import LinearProgress from '@material-ui/core/LinearProgress'; function pad(number, length) { - - var str = '' + number; - while (str.length < length) { - str = '0' + str; - } - - return str; - + var str = String(number); + while (str.length < length) { + str = '0' + str; } - -Date.prototype.DDMMYYYYatHHMM = function () { - var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); - var dd = pad(this.getDate(), 2); - var hh = pad(this.getHours(), 2); - var mm = pad(this.getMinutes(), 2) - - return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); - }; + + return str; +} + +Date.prototype.DDMMYYYYatHHMM = function() { + var yyyy = this.getFullYear().toString(); + var MM = pad(this.getMonth() + 1, 2); + var dd = pad(this.getDate(), 2); + var hh = pad(this.getHours(), 2); + var mm = pad(this.getMinutes(), 2); + + return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); +}; class PollReview extends Component { + state = { + isSubmitting: false + }; - state = { - isSubmitting : false + componentDidMount() { + if (this.props.poll.endDate === null || this.props.poll.endDate === undefined) { + const { history } = this.props; + history.push('/'); } + } - componentDidMount(){ - if(this.props.poll.endDate === null || this.props.poll.endDate === undefined){ - const {history} = this.props; - history.push('/'); - } - } + sign = async () => { + this.setState({ isSubmitting: true }); - sign = async () => { - this.setState({isSubmitting: true}); - - const {history, poll} = this.props; - const addPollOnlyEndTime = PollManager.methods["addPoll(uint256,bytes,uint8)"]; + const { history, poll } = this.props; + const addPollOnlyEndTime = PollManager.methods['addPoll(uint256,bytes,uint8)']; - const endTime = parseInt(poll.endDate.getTime() / 1000, 10); - const pollObj = { - 'title': poll.title, - 'description': poll.description, - 'ballots': poll.options - } - const pollObjString = JSON.stringify(pollObj); + const endTime = parseInt(poll.endDate.getTime() / 1000, 10); + const pollObj = { + title: poll.title, + description: poll.description, + ballots: poll.options + }; + const pollObjString = JSON.stringify(pollObj); - const ipfsHash = await EmbarkJS.Storage.saveText(pollObjString); - const encodedDesc = web3.utils.toHex(ipfsHash); - const toSend = addPollOnlyEndTime(endTime, encodedDesc, pollObj.ballots.length || 0); - const gasEstimated = await toSend.estimateGas({from: web3.eth.defaultAccount}); - const transaction = toSend.send({gas: gasEstimated + 100000, from: web3.eth.defaultAccount}); + const ipfsHash = await EmbarkJS.Storage.saveText(pollObjString); + const encodedDesc = web3.utils.toHex(ipfsHash); + const toSend = addPollOnlyEndTime(endTime, encodedDesc, pollObj.ballots.length || 0); + const gasEstimated = await toSend.estimateGas({ from: web3.eth.defaultAccount }); + const transaction = toSend.send({ gas: gasEstimated + 100000, from: web3.eth.defaultAccount }); - transaction.on('transactionHash', hash => { - this.props.setPollTransactionHash(hash); - this.props.setPollTransactionPromise(transaction); - history.push('/poll/results/'); - }); + transaction.on('transactionHash', hash => { + this.props.setPollTransactionHash(hash); + this.props.setPollTransactionPromise(transaction); + history.push('/poll/results/'); + }); - transaction.catch(err => { - this.setState({isSubmitting: false}); - }); - } - + transaction.catch(error => { + this.setState({ isSubmitting: false }); + }); + }; - render() { - const {poll} = this.props; + render() { + const { poll } = this.props; - if(!poll.options) return null; + if (!poll.options) return null; - return - + return ( + +
- Review details + Review details -
- {poll.title}

- {poll.description} -
- Poll starts: - Today (upon publishing)

- Poll ends: - {poll.endDate.DDMMYYYYatHHMM()} -
- -

Options
- { - poll.options.map((item, i) => { - return
- {item.title} - {item.content} -
- }) - } +
+ + {poll.title} +
+
+
+ {poll.description} +
+ + Poll starts: + + + Today (upon publishing) +
+
+
+ + Poll ends: + + + {poll.endDate.DDMMYYYYatHHMM()} +
+ + +
+
+ Options +
+ {poll.options.map((item, i) => { + return ( +
+ {item.title} + {item.content} +
+ ); + })} +
- +
- ; - } + + ); + } } export default withRouter(PollReview); diff --git a/app/components/flow/create/PollSchedule.js b/app/components/flow/create/PollSchedule.js index c29b358..5003f7d 100644 --- a/app/components/flow/create/PollSchedule.js +++ b/app/components/flow/create/PollSchedule.js @@ -1,14 +1,11 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; import PropTypes from 'prop-types'; import Button from '@material-ui/core/Button'; import LinearProgress from '@material-ui/core/LinearProgress'; import { InlineDateTimePicker } from 'material-ui-pickers'; -import InfiniteCalendar, { - Calendar, - withRange, - } from 'react-infinite-calendar'; +import InfiniteCalendar, { Calendar, withRange } from 'react-infinite-calendar'; import 'react-infinite-calendar/styles.css'; import { setHours, setMinutes, getHours, getMinutes } from 'date-fns'; import { monthNames, timeValues, timeGroups } from '../../standard/constants'; @@ -17,187 +14,188 @@ import TimePickerDialog from './TimePickerDialog'; const CalendarWithRange = withRange(Calendar); Date.prototype.addDays = function(days) { - var date = new Date(this.valueOf()); - date.setDate(date.getDate() + days); - return date; -} + var date = new Date(this.valueOf()); + date.setDate(date.getDate() + days); + return date; +}; class PollSchedule extends Component { + static propTypes = { + poll: PropTypes.object, + assignToPoll: PropTypes.func + }; - static propTypes = { - poll: PropTypes.object, - assignToPoll: PropTypes.func, + state = { + endDate: false, + error: '', + timeDialog: false, + timeValues: { + hour: '00', + minute: '00', + ampm: 'AM' + } + }; + componentDidMount() { + const { endDate, options } = this.props.poll; + if (endDate !== undefined) { + const minute = `${getMinutes(endDate)}`; + const hour = `${getHours(endDate)}`; + const ampm = hour > 12 ? 'PM' : 'AM'; + const timeValues = { hour, minute, ampm }; + + this.setState({ endDate: endDate, timeValues }); + } else { + const currentDate = new Date(); + const hrs = getHours(currentDate); + const mins = getMinutes(currentDate); + const minute = mins < 10 ? '0' + mins : `${mins}`; + let hour = hrs % 12; + hour = hour ? `${hour}` : 12; + hour = hour < 10 ? '0' + hour : `${hour}`; + const ampm = hrs >= 12 ? 'PM' : 'AM'; + const timeValues = { hour, minute, ampm }; + this.setState({ endDate: new Date().addDays(15), timeValues }); } - state = { - endDate: false, - error: '', - timeDialog: false, - timeValues: { - hour: '00', - minute: '00', - ampm: 'AM' + if (!options) { + const { history } = this.props; + history.push('/'); + } + } + + handleDateChange = date => { + this.props.assignToPoll({ endDate: date.end }); + this.setState({ endDate: date.end }); + }; + + handleTimeChange = (name, value) => { + const { endDate } = this.state; + this.setState(({ timeValues }) => ({ + timeValues: { + ...timeValues, + [name]: value + } + })); + if (name == 'hour') { + const updatedHour = setHours(endDate, value); + this.setState({ endDate: updatedHour }); + } else if (name == 'minute') { + const updatedMinute = setMinutes(endDate, value); + this.setState({ endDate: updatedMinute }); + } else { + let newHour; + if (value == 'AM') { + if (getHours(endDate) >= 12) { + newHour = getHours(endDate) - 12; + const updatedHour = setHours(endDate, newHour); + this.setState({ endDate: updatedHour }); } - } - - componentDidMount(){ - const { endDate, options } = this.props.poll; - if(endDate !== undefined){ - const minute = `${getMinutes(endDate)}` - const hour = `${getHours(endDate)}` - const ampm = hour > 12 ? 'PM' : 'AM' - const timeValues = { hour, minute, ampm } - - this.setState({endDate: endDate, timeValues}); - - } else { - const currentDate = new Date(); - const hrs = getHours(currentDate) - const mins = getMinutes(currentDate) - const minute = mins < 10 ? '0' + mins : `${mins}` - let hour = hrs % 12 - hour = hour ? `${hour}` : 12 - hour = hour < 10 ? '0' + hour: `${hour}` - const ampm = hrs >= 12 ? 'PM' : 'AM' - const timeValues = { hour, minute, ampm } - this.setState({endDate: (new Date()).addDays(15), timeValues }); - } - - if(!options){ - const {history} = this.props; - history.push('/'); + } else { + if (getHours(endDate) < 12) { + newHour = getHours(endDate) + 12; + const updatedHour = setHours(endDate, newHour); + this.setState({ endDate: updatedHour }); } + } } + }; - handleDateChange = date => { - this.props.assignToPoll({endDate: date.end}); - this.setState({ endDate: date.end }); + continue = () => { + const { endDate } = this.state; + const { history } = this.props; + if (endDate != null) { + this.props.assignToPoll({ endDate: endDate }); + history.push('/poll/review'); + } else { + this.setState({ error: 'Required' }); } + }; - handleTimeChange = (name, value) => { - const { endDate } = this.state; - this.setState(({timeValues}) => ({ - timeValues: { - ...timeValues, - [name]: value - } - })); - if(name == 'hour') { - const updatedHour = setHours(endDate, value) - this.setState({ endDate: updatedHour}) - } else if(name == 'minute') { - const updatedMinute = setMinutes(endDate, value) - this.setState({ endDate: updatedMinute}) - } else { - let newHour; - if(value == 'AM') { - if(getHours(endDate) >= 12) { - newHour = getHours(endDate) - 12 - const updatedHour = setHours(endDate, newHour) - this.setState({ endDate: updatedHour }) - } - } else { - if(getHours(endDate) < 12) { - newHour = getHours(endDate) + 12 - const updatedHour = setHours(endDate, newHour) - this.setState({ endDate: updatedHour }) - } - } - } - - } + formatAMPM = date => { + let hours = date.getHours(); + let minutes = date.getMinutes(); + let ampm = hours >= 12 ? 'PM' : 'AM'; + hours = hours % 12; + hours = hours || 12; // the hour '0' should be '12' + minutes = minutes < 10 ? '0' + minutes : minutes; + let strTime = hours + ':' + minutes + ' ' + ampm; + return strTime; + }; - continue = () => { - const {endDate} = this.state; - const {history} = this.props; - if(endDate != null){ - this.props.assignToPoll({endDate: endDate}); - history.push('/poll/review'); - } else { - this.setState({error: "Required"}) - } - } + toggleTimeDialog = prevState => { + this.setState({ + timeDialog: !prevState.timeDialog + }); + }; - formatAMPM = (date) => { - let hours = date.getHours(); - let minutes = date.getMinutes(); - let ampm = hours >= 12 ? 'PM' : 'AM'; - hours = hours % 12; - hours = hours ? hours : 12; // the hour '0' should be '12' - minutes = minutes < 10 ? '0'+minutes : minutes; - let strTime = hours + ':' + minutes + ' ' + ampm; - return strTime; - } + closeTimeDialog = () => { + this.setState({ + timeDialog: false + }); + }; - toggleTimeDialog = prevState => { - this.setState({ - timeDialog: !prevState.timeDialog - }); - }; + render() { + const { endDate, timeDialog, timeValues } = this.state; + const today = new Date(); - closeTimeDialog = () => { - this.setState({ - timeDialog: false - }); - }; - - - render() { - const { endDate, timeDialog, timeValues } = this.state; - const today = new Date(); - - - return + return ( +
- Create a Poll - Set the end date and time for the poll. -
- -
+ Create a Poll + + Set the end date and time for the poll. + +
+ +
-
-
- Ends: -
- { endDate && `${monthNames[endDate.getMonth()]} ${endDate.getDate()} ` } -
-
- { endDate && `at ${this.formatAMPM(endDate)}`} -
-
-
Edit Time
- +
+
+ Ends: +
{endDate && `${monthNames[endDate.getMonth()]} ${endDate.getDate()} `}
+
{endDate && `at ${this.formatAMPM(endDate)}`}
- +
+ Edit Time +
+ +
+
- ; - } + + ); + } } export default withRouter(PollSchedule); diff --git a/app/components/flow/create/PollTitle.js b/app/components/flow/create/PollTitle.js index 6b72d15..15f242c 100644 --- a/app/components/flow/create/PollTitle.js +++ b/app/components/flow/create/PollTitle.js @@ -1,82 +1,84 @@ -import React, {Component, Fragment} from 'react'; -import { withRouter } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' +import React, { Component, Fragment } from 'react'; +import { withRouter } from 'react-router-dom'; +import Typography from '@material-ui/core/Typography'; import TextField from '@material-ui/core/TextField'; import FormHelperText from '@material-ui/core/FormHelperText'; import LinearProgress from '@material-ui/core/LinearProgress'; import Button from '@material-ui/core/Button'; - class PollTitle extends Component { + state = { + title: '', + error: '' + }; - state = { - title: '', - error: '' + componentDidMount() { + if (!web3.eth.defaultAccount) { + this.props.history.push('/'); } - componentDidMount(){ - if(!web3.eth.defaultAccount){ - this.props.history.push('/'); - } - - if(this.props.poll.title !== undefined){ - this.setState({title: this.props.poll.title}); - } else { - this.props.assignToPoll({title: ''}); - } + if (this.props.poll.title !== undefined) { + this.setState({ title: this.props.poll.title }); + } else { + this.props.assignToPoll({ title: '' }); } + } - handleChange = (event) => { - this.setState({error: ''}); - if(event.target.value.length <= 70){ - this.props.assignToPoll({title: event.target.value}); - this.setState({title: event.target.value}); - } + handleChange = event => { + this.setState({ error: '' }); + if (event.target.value.length <= 70) { + this.props.assignToPoll({ title: event.target.value }); + this.setState({ title: event.target.value }); } + }; - continue = () => { - const {title} = this.state; - const {history} = this.props; + continue = () => { + const { title } = this.state; + const { history } = this.props; - if(title.trim() != ''){ - this.props.assignToPoll({title}); - history.push('/poll/description'); - } else { - this.setState({error: "Required"}) - } + if (title.trim() != '') { + this.props.assignToPoll({ title }); + history.push('/poll/description'); + } else { + this.setState({ error: 'Required' }); } + }; - render() { - return + render() { + return ( +
- Create a Poll -
+ Create a Poll +
-
- {this.state.error && {this.state.error}} - {this.state.title.length} of 70 +
+ {this.state.error && {this.state.error}} + {this.state.title.length} of 70
- +
-
; - } +
+ ); + } } export default withRouter(PollTitle); diff --git a/app/components/flow/create/TimePickerDialog.js b/app/components/flow/create/TimePickerDialog.js index 90bb925..3448318 100644 --- a/app/components/flow/create/TimePickerDialog.js +++ b/app/components/flow/create/TimePickerDialog.js @@ -1,30 +1,28 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; import Picker from 'react-mobile-picker'; import { timeGroups } from '../../standard/constants'; import Dialog from '@material-ui/core/Dialog'; import Button from '@material-ui/core/Button'; const dialogStyle = { - width: '80vh', + width: '80vh' }; export default class TimePickerDialog extends Component { render() { const { timeDialog, handleTimeChange, closeTimeDialog, timeValues } = this.props; return ( - +
Set end time
- -
- ) + ); } } diff --git a/app/components/flow/wallet/ConnectYourWallet.js b/app/components/flow/wallet/ConnectYourWallet.js index fca08ea..1fb3863 100644 --- a/app/components/flow/wallet/ConnectYourWallet.js +++ b/app/components/flow/wallet/ConnectYourWallet.js @@ -1,9 +1,9 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component} from 'react'; -import Typography from '@material-ui/core/Typography' -import DappToken from 'Embark/contracts/DappToken'; -import { withRouter } from 'react-router-dom' +import React, { Component } from 'react'; +import Typography from '@material-ui/core/Typography'; +import DappToken from 'Embark/contracts/DappToken'; +import { withRouter } from 'react-router-dom'; import PollManager from 'Embark/contracts/PollManager'; import utils from '../../../utils/utils'; @@ -11,56 +11,66 @@ class ConnectYourWallet extends Component { connectWallet = async () => { // TODO: extract this to utils, this code is repeated here, in other wallets and in How voting works - const {history, polls, updateBalances, idPoll, decimals} = this.props; + const { history, polls, updateBalances, idPoll, decimals } = this.props; const poll = polls[idPoll]; let cont = true; if (window.ethereum) { try { - await ethereum.enable(); - web3.setProvider(ethereum); - const accounts = await web3.eth.getAccounts(); - web3.eth.defaultAccount = accounts[0]; + await ethereum.enable(); + web3.setProvider(ethereum); + const accounts = await web3.eth.getAccounts(); + web3.eth.defaultAccount = accounts[0]; } catch (error) { cont = false; } } - if(cont){ - const tknVotes = await PollManager.methods.getVote(idPoll, web3.eth.defaultAccount).call({from: web3.eth.defaultAccount}); + if (cont) { + const tknVotes = await PollManager.methods + .getVote(idPoll, web3.eth.defaultAccount) + .call({ from: web3.eth.defaultAccount }); const votes = tknVotes.map(x => Math.sqrt(parseInt(utils.fromTokenDecimals(x, decimals)))); - if(web3.currentProvider.isStatus){ - if(idPoll == 'poll-creation'){ + if (web3.currentProvider.isStatus) { + if (idPoll == 'poll-creation') { history.push('/poll/create'); } else { - const tokenBalance = await DappToken.methods.balanceOfAt(web3.eth.defaultAccount, poll._startBlock).call({from: web3.eth.defaultAccount}); + const tokenBalance = await DappToken.methods + .balanceOfAt(web3.eth.defaultAccount, poll._startBlock) + .call({ from: web3.eth.defaultAccount }); const ethBalance = await web3.eth.getBalance(web3.eth.defaultAccount); updateBalances(idPoll, tokenBalance, ethBalance, votes); history.push('/votingCredits/' + idPoll); } } else { - window.location.href = "https://get.status.im/browse/" + location.href.replace(/^http(s?):\/\//, ''); + window.location.href = 'https://get.status.im/browse/' + location.href.replace(/^http(s?):\/\//, ''); } } - } + }; - render(){ - const {idPoll, symbol} = this.props; + render() { + const { idPoll, symbol } = this.props; - return
- Connect your wallet - To start voting, connect to a wallet where you hold your {symbol} assets. -
- -
-
- - - -
-
; + return ( +
+ Connect your wallet + + To start voting, connect to a wallet where you hold your {symbol} assets. + +
+ +
+
+ + + +
+
+ ); } } diff --git a/app/components/flow/wallet/ExternalWallet.js b/app/components/flow/wallet/ExternalWallet.js index 50c4560..d52e6ca 100644 --- a/app/components/flow/wallet/ExternalWallet.js +++ b/app/components/flow/wallet/ExternalWallet.js @@ -1,59 +1,60 @@ -import React, {Component} from 'react'; -import { withRouter } from 'react-router-dom' -import DappToken from 'Embark/contracts/DappToken'; -import PollManager from 'Embark/contracts/PollManager'; +import React, { Component } from 'react'; +import { withRouter } from 'react-router-dom'; +import DappToken from 'Embark/contracts/DappToken'; +import PollManager from 'Embark/contracts/PollManager'; import utils from '../../../utils/utils'; class ExternalWallet extends Component { - - componentDidUpdate(prevProps){ - if (this.props.polls !== prevProps.polls && this.props.polls) { - this.connectWallet(); - } + componentDidUpdate(prevProps) { + if (this.props.polls !== prevProps.polls && this.props.polls) { + this.connectWallet(); + } + } + + componentDidMount() { + this.connectWallet(); + } + + connectWallet = async () => { + const { history, polls, updateBalances, idPoll, decimals } = this.props; + if (!polls) return; + + const poll = polls.find(p => p.idPoll == idPoll); + if (!poll) return null; + + let cont = true; + if (window.ethereum) { + try { + await ethereum.enable(); + web3.setProvider(ethereum); + const accounts = await web3.eth.getAccounts(); + web3.eth.defaultAccount = accounts[0]; + } catch (error) { + cont = false; + } } - componentDidMount(){ - this.connectWallet(); + if (cont) { + // TODO: extract this code to utils. It's repeated in ConnectYourWallt, ExternalWallet and HowVotingWorks + const tknVotes = await PollManager.methods + .getVote(idPoll, web3.eth.defaultAccount) + .call({ from: web3.eth.defaultAccount }); + + // TODO: use decimals + const votes = tknVotes.map(x => Math.sqrt(parseInt(utils.fromTokenDecimals(x, decimals)))); + const tokenBalance = await DappToken.methods + .balanceOfAt(web3.eth.defaultAccount, poll._startBlock) + .call({ from: web3.eth.defaultAccount }); + const ethBalance = await web3.eth.getBalance(web3.eth.defaultAccount); + updateBalances(idPoll, tokenBalance, ethBalance, votes); + + history.push('/votingCredits/' + idPoll); } + }; - connectWallet = async () => { - const {history, polls, updateBalances, idPoll, decimals} = this.props; - if(!polls) return; - - const poll = polls.find(p => p.idPoll == idPoll); - if(!poll) return null; - - - let cont = true; - if (window.ethereum) { - try { - await ethereum.enable(); - web3.setProvider(ethereum); - const accounts = await web3.eth.getAccounts(); - web3.eth.defaultAccount = accounts[0]; - } catch (error) { - cont = false; - } - } - - if(cont){ - // TODO: extract this code to utils. It's repeated in ConnectYourWallt, ExternalWallet and HowVotingWorks - const tknVotes = await PollManager.methods.getVote(idPoll, web3.eth.defaultAccount).call({from: web3.eth.defaultAccount}); - - // TODO: use decimals - const votes = tknVotes.map(x => Math.sqrt(parseInt( utils.fromTokenDecimals(x, decimals)))); - const tokenBalance = await DappToken.methods.balanceOfAt(web3.eth.defaultAccount, poll._startBlock).call({from: web3.eth.defaultAccount}); - const ethBalance = await web3.eth.getBalance(web3.eth.defaultAccount); - updateBalances(idPoll, tokenBalance, ethBalance, votes); - - - history.push('/votingCredits/' + idPoll); - } - }; - - render(){ - return null; - } + render() { + return null; + } } -export default withRouter(ExternalWallet); \ No newline at end of file +export default withRouter(ExternalWallet); diff --git a/app/components/flow/wallet/OtherWallets.js b/app/components/flow/wallet/OtherWallets.js index f9193f5..0ee454c 100644 --- a/app/components/flow/wallet/OtherWallets.js +++ b/app/components/flow/wallet/OtherWallets.js @@ -1,20 +1,20 @@ -import {Link} from "react-router-dom"; +import { Link } from 'react-router-dom'; import Button from '@material-ui/core/Button'; -import React, {Component, Fragment} from 'react'; +import React, { Component, Fragment } from 'react'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import Typography from '@material-ui/core/Typography'; import HelpDialog from '../HelpDialog'; // TODO: extract to utils -Date.prototype.DDMMYYYYatHHMM = function () { +Date.prototype.DDMMYYYYatHHMM = function() { var yyyy = this.getFullYear().toString(); - var MM = pad(this.getMonth() + 1,2); + var MM = pad(this.getMonth() + 1, 2); var dd = pad(this.getDate(), 2); var hh = pad(this.getHours(), 2); - var mm = pad(this.getMinutes(), 2) + var mm = pad(this.getMinutes(), 2); - return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); + return dd + '/' + MM + '/' + yyyy + ' at ' + hh + ':' + mm + (this.getHours() > 12 ? 'pm' : 'am'); }; function getDate() { @@ -23,19 +23,17 @@ function getDate() { } function pad(number, length) { - - var str = '' + number; + var str = String(number); while (str.length < length) { - str = '0' + str; + str = '0' + str; } return str; - } class OtherWallets extends Component { state = { - open: false, + open: false }; handleClickOpen = () => { @@ -48,69 +46,78 @@ class OtherWallets extends Component { render() { const props = this.props; - + let poll = null; let d = new Date(); - if(!props.noWeb3Provider){ - if(!props.polls){ + if (!props.noWeb3Provider) { + if (!props.polls) { return null; } - - if(props.idPoll != "poll-creation"){ + if (props.idPoll != 'poll-creation') { poll = props.polls.find(p => p.idPoll == props.idPoll); - if(!poll) return null; + if (!poll) return null; d = new Date(poll.blockInfo.timestamp * 1000); } + } - } - - return
- Connect with a wallet with {this.props.symbol} in it. - { !props.noWeb3Provider && poll && - Poll creation date: {d.DDMMYYYYatHHMM()} - } - Using your desktop computer - - - - MetaMask - - - If you keep your {this.props.symbol} in MetaMask, please open vote.status.im in Google Chrome and make sure you are connected to the account where you keep your {this.props.symbol}. - - - - - - - Ledger or Trezor - - - If you keep your {this.props.symbol} in a Ledger or Trezor, please connect the device to MetaMask. Then open vote.status.im in Google Chrome with your hardware wallet’s account selected in metamask. - - - - - - - {this.props.symbol} on Exchanges - - - We are sorry. {this.props.symbol} held on exchanges don’t qualify for voting. - To vote in the next poll, move your {this.props.symbol} to a wallet where you control the private keys. - - - -

Need help? Chat with us

-
-
- -
- -
+ return ( + +
+ Connect with a wallet with {this.props.symbol} in it. + {!props.noWeb3Provider && poll && ( + + Poll creation date: {d.DDMMYYYYatHHMM()} + + )} + Using your desktop computer + + + + MetaMask + + + If you keep your {this.props.symbol} in MetaMask, please open vote.status.im in Google Chrome and make + sure you are connected to the account where you keep your {this.props.symbol}. + + + + + + + Ledger or Trezor + + + If you keep your {this.props.symbol} in a Ledger or Trezor, please connect the device to MetaMask. Then + open vote.status.im in Google Chrome with your hardware wallet’s account selected in metamask. + + + + + + + {this.props.symbol} on Exchanges + + + We are sorry. {this.props.symbol} held on exchanges don’t qualify for voting. To vote in the next poll, + move your {this.props.symbol} to a wallet where you control the private keys. + + + +

+ Need help? Chat with us +

+
+
+ + + +
+ +
+ ); } } -export default OtherWallets; \ No newline at end of file +export default OtherWallets; diff --git a/app/components/standard/NoConnection.js b/app/components/standard/NoConnection.js index 4853433..d8d4d7a 100644 --- a/app/components/standard/NoConnection.js +++ b/app/components/standard/NoConnection.js @@ -1,28 +1,37 @@ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import Button from '@material-ui/core/Button'; -import Typography from '@material-ui/core/Typography' +import Typography from '@material-ui/core/Typography'; import { withRouter } from 'react-router-dom'; -import { HashRouter as Router, Route, Link, Switch } from "react-router-dom"; +import { HashRouter as Router, Route, Link, Switch } from 'react-router-dom'; const NoConnection = () => { return ( - { - return
- Status SNT Voting - To start voting, connect to a wallet where you hold your SNT - -
- - - -
-
; - }} /> + { + return ( +
+ Status SNT Voting + To start voting, connect to a wallet where you hold your SNT + +
+ + + +
+
+ ); + }} + /> ); }; -NoConnection.displayName = "NoConnection"; +NoConnection.displayName = 'NoConnection'; -export default withRouter(NoConnection) +export default withRouter(NoConnection); diff --git a/app/components/standard/Web3Render.js b/app/components/standard/Web3Render.js index f2cf7a0..be3ae92 100644 --- a/app/components/standard/Web3Render.js +++ b/app/components/standard/Web3Render.js @@ -1,15 +1,17 @@ import React, { Fragment } from 'react'; import NoConnection from './NoConnection'; -const NoWeb3 = () => ( -
- NO WEB3 Provider detected -
-) +const NoWeb3 = () =>
NO WEB3 Provider detected
; const Web3Render = ({ ready, children }) => ( - {ready ? {children} :
} + {ready ? ( + {children} + ) : ( +
+ +
+ )}
); diff --git a/app/components/standard/constants.js b/app/components/standard/constants.js index 9a43b27..5877112 100644 --- a/app/components/standard/constants.js +++ b/app/components/standard/constants.js @@ -1,13 +1,71 @@ // Month names array for calendar -export const monthNames = [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -]; - +export const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // Time dicktionary for picker export const timeGroups = { - hour: ['00','01','02','03','04','05','06','07','08','09','10','11','12'], - minute: ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60'], + hour: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], + minute: [ + '00', + '01', + '02', + '03', + '04', + '05', + '06', + '07', + '08', + '09', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + '24', + '25', + '26', + '27', + '28', + '29', + '30', + '31', + '32', + '33', + '34', + '35', + '36', + '37', + '38', + '39', + '40', + '41', + '42', + '43', + '44', + '45', + '46', + '47', + '48', + '49', + '50', + '51', + '52', + '53', + '54', + '55', + '56', + '57', + '58', + '59', + '60' + ], ampm: ['AM', 'PM'] }; diff --git a/app/components/standard/style.js b/app/components/standard/style.js index 1d6ad57..bd78497 100644 --- a/app/components/standard/style.js +++ b/app/components/standard/style.js @@ -1,9 +1,9 @@ export default { NoEthereumSection: { - maxWidth: '980px', - margin: '0 auto', - textAlign: 'center', - fontSize: '24px' + maxWidth: '980px', + margin: '0 auto', + textAlign: 'center', + fontSize: '24px' }, ImgHeaderLogo: { width: '264px', @@ -15,7 +15,7 @@ export default { marginBottom: '40px' }, PNotFound: { - opacity: 0.50, + opacity: 0.5, width: '925px', display: 'inline-block', marginTop: '50px', @@ -66,6 +66,4 @@ export default { borderRadius: '4px', margin: '0 20px' } - -} - +}; diff --git a/app/components/standard/utils.js b/app/components/standard/utils.js index 0541bc4..000c6fc 100644 --- a/app/components/standard/utils.js +++ b/app/components/standard/utils.js @@ -3,7 +3,7 @@ import BigNumber from 'bignumber.js'; // By default BigNumber's `toString` method converts to exponential notation if the value has // more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number BigNumber.config({ - EXPONENTIAL_AT: 1000, + EXPONENTIAL_AT: 1000 }); export { BigNumber }; diff --git a/app/components/token-ui.js b/app/components/token-ui.js index 6ee1522..b97370a 100644 --- a/app/components/token-ui.js +++ b/app/components/token-ui.js @@ -1,5 +1,5 @@ import React from 'react'; -import web3 from "Embark/web3" +import web3 from 'Embark/web3'; import EmbarkJS from 'Embark/EmbarkJS'; import DappToken from 'Embark/contracts/DappToken'; import FormControl from '@material-ui/core/FormControl'; @@ -8,7 +8,6 @@ import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button'; import { withStyles } from '@material-ui/core/styles'; - const styles = () => ({ mlb: { marginLeft: '1rem', @@ -22,114 +21,117 @@ const styles = () => ({ }); class TokenUI extends React.Component { - - constructor(props) { - super(props); - this.state = { - address: "", - amountToMint: "100000000000000000000", - accountBalance: 0, - accountB: web3.eth.defaultAccount, - balanceOf: 0, - logs: [] - } - } - - componentDidMount(){ - EmbarkJS.onReady(async () => { - this.setState({address: web3.eth.defaultAccount}); - }); - } - - handleMintAmountChange(e){ - this.setState({amountToMint: e.target.value}); - } - - mint(e){ - e.preventDefault(); - - var value = parseInt(this.state.amountToMint, 10); - var address = this.state.address; - - DappToken.methods.controller().call() - .then((controller) => { - return DappToken.methods.generateTokens(address, value.toString()) - .send({from: controller, gasLimit: 1000000}); - }) - .then(console.log); - - this._addToLog(DappToken.options.address +".mint("+value+").send({from: " + web3.eth.defaultAccount + "})"); - } - - getBalance(e){ - e.preventDefault(); - - if (EmbarkJS.isNewWeb3()) { - DappToken.methods.balanceOf(web3.eth.defaultAccount).call() - .then(_value => this.setState({accountBalance: _value})) - } else { - DappToken.balanceOf(web3.eth.defaultAccount) - .then(_value => this.x({valueGet: _value})) - } - this._addToLog(DappToken.options.address + ".balanceOf(" + web3.eth.defaultAccount + ")"); - } - - _addToLog(txt){ - this.state.logs.push(txt); - this.setState({logs: this.state.logs}); - } - - render(){ - const { classes } = this.props; - - return ( -

1. Mint your token

- - - this.setState({address: e.target.value}) } - variant="outlined" - /> - this.handleMintAmountChange(e)} - variant="outlined" - /> - - - - -

2. Read your account token balance

- - -
- You text token balance is {this.state.accountBalance} -
- - -
-
- -

3. Contract Calls

-

Javascript calls being made:

-
- { - this.state.logs.map((item, i) =>

{item}

) - } -
-
- ); - } + constructor(props) { + super(props); + this.state = { + address: '', + amountToMint: '100000000000000000000', + accountBalance: 0, + accountB: web3.eth.defaultAccount, + balanceOf: 0, + logs: [] + }; } + componentDidMount() { + EmbarkJS.onReady(async () => { + this.setState({ address: web3.eth.defaultAccount }); + }); + } + + handleMintAmountChange(e) { + this.setState({ amountToMint: e.target.value }); + } + + mint(e) { + e.preventDefault(); + + var value = parseInt(this.state.amountToMint, 10); + var address = this.state.address; + + DappToken.methods + .controller() + .call() + .then(controller => { + return DappToken.methods + .generateTokens(address, value.toString()) + .send({ from: controller, gasLimit: 1000000 }); + }) + .then(console.log); + + this._addToLog(DappToken.options.address + '.mint(' + value + ').send({from: ' + web3.eth.defaultAccount + '})'); + } + + getBalance(e) { + e.preventDefault(); + + if (EmbarkJS.isNewWeb3()) { + DappToken.methods + .balanceOf(web3.eth.defaultAccount) + .call() + .then(_value => this.setState({ accountBalance: _value })); + } else { + DappToken.balanceOf(web3.eth.defaultAccount).then(_value => this.x({ valueGet: _value })); + } + this._addToLog(DappToken.options.address + '.balanceOf(' + web3.eth.defaultAccount + ')'); + } + + _addToLog(txt) { + this.state.logs.push(txt); + this.setState({ logs: this.state.logs }); + } + + render() { + const { classes } = this.props; + + return ( + +

1. Mint your token

+ + + this.setState({ address: e.target.value })} + variant="outlined" + /> + this.handleMintAmountChange(e)} + variant="outlined" + /> + + + + +

2. Read your account token balance

+ + +
+ You text token balance is {this.state.accountBalance} +
+ + +
+
+ +

3. Contract Calls

+

Javascript calls being made:

+
+ {this.state.logs.map((item, i) => ( +

{item}

+ ))} +
+
+ ); + } +} + export default withStyles(styles)(TokenUI); - \ No newline at end of file diff --git a/app/dapp.js b/app/dapp.js index f29f2c5..397c032 100644 --- a/app/dapp.js +++ b/app/dapp.js @@ -1,14 +1,14 @@ import React, { Fragment } from 'react'; import ReactDOM from 'react-dom'; -import web3 from "Embark/web3"; +import web3 from 'Embark/web3'; import EmbarkJS from 'Embark/EmbarkJS'; import PollManager from 'Embark/contracts/PollManager'; import Voting from './components/Voting'; -import DappToken from 'Embark/contracts/DappToken'; +import DappToken from 'Embark/contracts/DappToken'; import { VotingContext } from './context'; import Web3Render from './components/standard/Web3Render'; import { getPolls, omitPolls } from './utils/polls'; -import { HashRouter as Router, Route, Switch } from "react-router-dom"; +import { HashRouter as Router, Route, Switch } from 'react-router-dom'; import OtherWallets from './components/flow/wallet/OtherWallets'; import Typography from '@material-ui/core/Typography'; import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'; @@ -23,11 +23,11 @@ const muiTheme = createMuiTheme({ root: { height: '44px', fontSize: '15px', - lineHeight: '22px', + lineHeight: '22px' }, label: { fontSize: '15px', - lineHeight: '22px', + lineHeight: '22px' } } } @@ -40,7 +40,7 @@ const TESTNET = 3; // #38 setTimeout(() => { - if(!(window.web3 || window.ethereum)){ + if (!(window.web3 || window.ethereum)) { window.location.reload(true); } }, 5000); @@ -48,84 +48,102 @@ setTimeout(() => { const pollsPerLoad = 3; class App extends React.Component { + state = { + admin: false, + pollOrder: 'NEWEST_ADDED', + web3Provider: true, + loading: true, + name: '----', + symbol: '', + decimals: '18', + networkName: '', + rawPolls: [], + pollsRequested: [], + start: 0, + end: pollsPerLoad + }; - state = { admin: false, pollOrder: 'NEWEST_ADDED', web3Provider: true, loading: true, name: '----', symbol: "", decimals: "18", networkName: "" , rawPolls: [], pollsRequested: [], start: 0, - end: pollsPerLoad}; - - componentDidMount(){ - EmbarkJS.onReady((err) => { + componentDidMount() { + EmbarkJS.onReady(err => { if (err) this.setState({ web3Provider: false }); else { - if(!web3.eth.defaultAccount){ - web3.eth.defaultAccount = "0x0000000000000000000000000000000000000000"; + if (!web3.eth.defaultAccount) { + web3.eth.defaultAccount = '0x0000000000000000000000000000000000000000'; } - - DappToken.methods.symbol().call({from: web3.eth.defaultAccount}).then(symbol => { - this.setState({symbol}); - }); - DappToken.methods.decimals().call({from: web3.eth.defaultAccount}).then(decimals => { - this.setState({decimals}); - }); + DappToken.methods + .symbol() + .call({ from: web3.eth.defaultAccount }) + .then(symbol => { + this.setState({ symbol }); + }); - DappToken.methods.name().call({from: web3.eth.defaultAccount}).then(name => { - this.setState({name}); - }) + DappToken.methods + .decimals() + .call({ from: web3.eth.defaultAccount }) + .then(decimals => { + this.setState({ decimals }); + }); + DappToken.methods + .name() + .call({ from: web3.eth.defaultAccount }) + .then(name => { + this.setState({ name }); + }); this._getPolls(); } web3.eth.net.getId((err, netId) => { - if(EmbarkJS.environment === 'testnet' && netId !== TESTNET){ - this.setState({web3Provider: false, networkName: "Ropsten"}); - } else if(EmbarkJS.environment === 'livenet' && netId !== MAINNET){ - this.setState({web3Provider: false, networkName: "Mainnet"}); + if (EmbarkJS.environment === 'testnet' && netId !== TESTNET) { + this.setState({ web3Provider: false, networkName: 'Ropsten' }); + } else if (EmbarkJS.environment === 'livenet' && netId !== MAINNET) { + this.setState({ web3Provider: false, networkName: 'Mainnet' }); } - }) - }) + }); + }); } - setAccount(_account){ - this.setState({account: _account}); + setAccount(_account) { + this.setState({ account: _account }); } - _loadIPFSContent = async (polls) => { - - - for(let i = 0; i < polls.length; i++){ + _loadIPFSContent = async polls => { + for (let i = 0; i < polls.length; i++) { try { let ipfsContent = await EmbarkJS.Storage.get(web3.utils.toAscii(polls[i]._description)); polls[i].content = JSON.parse(ipfsContent); - } catch(err){ - console.log(err); + } catch (error) { + console.log(error); } } let oPolls = {}; - for(let i = 0; i < polls.length; i++){ + for (let i = 0; i < polls.length; i++) { oPolls[polls[i].idPoll] = polls[i]; } this.setState({ rawPolls: oPolls, loading: false }); - } + }; _getPolls = async () => { this.setState({ loading: true }); const { nPolls, poll } = PollManager.methods; - const polls = await nPolls().call({from: web3.eth.defaultAccount}); - if (polls) getPolls(polls, poll) - .then(omitPolls) - .then(rawPolls => { - rawPolls = rawPolls.sort((a,b) => { - if(a.idPoll > b.idPoll) return -1; - if(a.idPoll < b.idPoll) return 1; - return 0; - }); - this.setState({rawPolls, loading: false}); - }); + const polls = await nPolls().call({ from: web3.eth.defaultAccount }); + if (polls) + getPolls(polls, poll) + .then(omitPolls) + .then(rawPolls => { + rawPolls = rawPolls.sort((a, b) => { + if (a.idPoll > b.idPoll) return -1; + if (a.idPoll < b.idPoll) return 1; + return 0; + }); + this.setState({ rawPolls, loading: false }); + }); else this.setState({ rawPolls: [], loading: false }); - } + }; - updatePoll = async (idPoll) => { + updatePoll = async idPoll => { const { poll, nPolls } = PollManager.methods; const { rawPolls } = this.state; const npolls = await nPolls().call(); @@ -135,134 +153,180 @@ class App extends React.Component { const updatedPoll = await poll(idPoll).call(); newPolls[idPoll] = { ...updatedPoll }; this.setState({ rawPolls: newPolls }); - } + }; appendToPoll = (idPoll, data) => { const { rawPolls } = this.state; const newPolls = [...rawPolls]; newPolls[idPoll] = { ...newPolls[idPoll], ...data }; this.setState({ rawPolls: newPolls }); - } + }; - setPollOrder = pollOrder => { this.setState({ pollOrder }); } + setPollOrder = pollOrder => { + this.setState({ pollOrder }); + }; _renderStatus(title, available) { let className = available ? 'pull-right status-online' : 'pull-right status-offline'; - return - {title} - - ; + return ( + + {title} + + + ); } - - replacePoll = (poll) => { + replacePoll = poll => { let rawPolls = this.state.rawPolls; - for(let i = 0; i < rawPolls.length; i++){ - if(rawPolls[i].idPoll === poll.idPoll){ + for (let i = 0; i < rawPolls.length; i++) { + if (rawPolls[i].idPoll === poll.idPoll) { rawPolls[i] = poll; - this.setState({rawPolls, t: new Date().getTime()}); + this.setState({ rawPolls, t: new Date().getTime() }); break; } } - } + }; + + loadPollContent = async poll => { + if (!poll) return; - loadPollContent = async (poll) => { - if(!poll) return; - let pollsRequested = this.state.pollsRequested; - if(!pollsRequested.includes(poll.idPoll)) pollsRequested.push(poll.idPoll); - this.setState({pollsRequested}); + if (!pollsRequested.includes(poll.idPoll)) pollsRequested.push(poll.idPoll); + this.setState({ pollsRequested }); let ipfsContent = await EmbarkJS.Storage.get(web3.utils.toAscii(poll._description)); poll.content = JSON.parse(ipfsContent); this.replacePoll(poll); - } + }; - - loadMorePolls = async (filterFn) => { + loadMorePolls = async filterFn => { let start = this.state.start + pollsPerLoad; let end = this.state.end + pollsPerLoad; - this.setState({start, end}); + this.setState({ start, end }); this.loadPollRange(filterFn, start, end); - } + }; resetPollCounter = () => { - this.setState({start: 0, end: pollsPerLoad}); - } - + this.setState({ start: 0, end: pollsPerLoad }); + }; loadPollRange = async (filterFn, start, end) => { let rawPolls = this.state.rawPolls; let polls = rawPolls.filter(filterFn).slice(start, end); - if(!polls.length) return; + if (!polls.length) return; let pollsRequested = this.state.pollsRequested; - if(!pollsRequested) return; + if (!pollsRequested) return; + + for (let i = 0; i < polls.length; i++) { + if (pollsRequested.includes(polls[i].idPoll)) continue; - for(let i = 0; i < polls.length; i++){ - if(pollsRequested.includes(polls[i].idPoll)) continue; - pollsRequested.push(polls[i].idPoll); let ipfsContent = await EmbarkJS.Storage.get(web3.utils.toAscii(polls[i]._description)); polls[i].content = JSON.parse(ipfsContent); - for(let i = 0; i < rawPolls.length; i++){ - for(let j = 0; j < polls.length; j++){ - if(rawPolls[i].idPoll == polls[j].idPoll){ + for (let i = 0; i < rawPolls.length; i++) { + for (let j = 0; j < polls.length; j++) { + if (rawPolls[i].idPoll == polls[j].idPoll) { rawPolls[i] = polls[j]; break; } } } - this.setState({rawPolls, pollsRequested}); + this.setState({ rawPolls, pollsRequested }); } - } + }; + render() { + let { web3Provider, networkName } = this.state; + const { + _getPolls, + updatePoll, + setPollOrder, + appendToPoll, + replacePoll, + loadPollContent, + resetPollCounter, + loadPollRange, + loadMorePolls + } = this; + const votingContext = { + getPolls: _getPolls, + updatePoll, + appendToPoll, + setPollOrder, + resetPollCounter, + replacePoll, + loadPollContent, + loadPollRange, + loadMorePolls, + ...this.state + }; - render(){ - let {web3Provider, networkName} = this.state; - const { _getPolls, updatePoll, setPollOrder, appendToPoll, replacePoll, loadPollContent, resetPollCounter, loadPollRange, loadMorePolls } = this; - const votingContext = { getPolls: _getPolls, updatePoll, appendToPoll, setPollOrder, resetPollCounter, replacePoll, loadPollContent, loadPollRange, loadMorePolls, ...this.state }; - - if(web3Provider) return - - - - - - - - ; - - if(networkName) return -
-

Please connect to {networkName} to continue.
-
-
; - - return + if (web3Provider) + return ( + + + + + + + + + ); + + if (networkName) + return ( + +
+ + +
+
+ Please connect to {networkName} to continue. +
+
+
+ ); + + return ( + + - { - return - - - - ; - } - } /> -
} /> + { + return ( + + + + + + ); + }} + /> + ( +
+ +
+ )} + />
-
; +
+ ); } } -ReactDOM.render(, document.getElementById('app')); +ReactDOM.render(, document.querySelector('#app')); diff --git a/app/js/index.js b/app/js/index.js index 5b0f64d..96a85b7 100644 --- a/app/js/index.js +++ b/app/js/index.js @@ -3,4 +3,3 @@ import EmbarkJS from 'Embark/EmbarkJS'; // import your contracts // e.g if you have a contract named SimpleStorage: //import SimpleStorage from 'Embark/contracts/SimpleStorage'; - diff --git a/app/ui/components/StatusLogo.js b/app/ui/components/StatusLogo.js index f77eee5..c9d32eb 100644 --- a/app/ui/components/StatusLogo.js +++ b/app/ui/components/StatusLogo.js @@ -1,10 +1,16 @@ -import React from "react" +import React from 'react'; const Status = props => ( - - + + ); diff --git a/app/utils/fetchIdeas.js b/app/utils/fetchIdeas.js index 2aee7a6..d822e85 100644 --- a/app/utils/fetchIdeas.js +++ b/app/utils/fetchIdeas.js @@ -1,6 +1,6 @@ import axios from 'axios'; -const repoFilter = (repo) => { +const repoFilter = repo => { const { path } = repo; if (path.includes('ideas')) { const split = path.split('/'); @@ -8,23 +8,22 @@ const repoFilter = (repo) => { if (path.includes('README')) return true; } return false; -} +}; -const convertToUrl = (repo) => { +const convertToUrl = repo => { const { path } = repo; const base = 'https://ideas.status.im/'; const suffix = path.split('.md')[0]; return `${base}${suffix}`; -} +}; const fetchContent = async () => { const response = await axios.get('https://api.github.com/repos/status-im/ideas/git/trees/master?recursive=1'); return response['data']['tree'].filter(repoFilter).map(convertToUrl); -} +}; const pluckIdeas = async () => { const data = await fetchContent(); return data; -} +}; export default pluckIdeas; - diff --git a/app/utils/polls.js b/app/utils/polls.js index c4c1323..214f3de 100644 --- a/app/utils/polls.js +++ b/app/utils/polls.js @@ -1,32 +1,32 @@ -import web3 from "Embark/web3" +import web3 from 'Embark/web3'; import MiniMeTokenInterface from 'Embark/contracts/MiniMeTokenInterface'; import PollManager from 'Embark/contracts/PollManager'; import DappToken from 'Embark/contracts/DappToken'; const excluded = { - // PROPER_LIGHT_CLIENT_SUPPORT : 3, + // PROPER_LIGHT_CLIENT_SUPPORT : 3, }; -export const getBalance = async (startBlock) => { +export const getBalance = async startBlock => { const { fromWei } = web3.utils; const { balanceOfAt } = DappToken.methods; const balance = await balanceOfAt(web3.eth.defaultAccount, startBlock - 1).call(); return fromWei(balance); -} +}; const fetchPollData = async (index, pollMethod) => { - const poll = await pollMethod(index).call({from: web3.eth.defaultAccount}); + const poll = await pollMethod(index).call({ from: web3.eth.defaultAccount }); const blockInfo = await web3.eth.getBlock(poll._startBlock); return { ...poll, idPoll: index, blockInfo }; -} +}; export const getPolls = (number, pollMethod) => { - const polls = []; - for (let i = number-1; i >= 0; i--) { + const polls = []; + for (let i = number - 1; i >= 0; i--) { polls.push(fetchPollData(i, pollMethod)); - } + } return Promise.all(polls.reverse()); -} +}; const excludedPolls = new Set(Object.values(excluded)); const exclusionFilter = (poll, idx) => !excludedPolls.has(idx); diff --git a/app/utils/utils.js b/app/utils/utils.js index dad9f03..536c6bb 100644 --- a/app/utils/utils.js +++ b/app/utils/utils.js @@ -1,42 +1,40 @@ - const BN = require('bn.js'); const numberToBN = require('number-to-bn'); const padLeft = (number, length) => { - var str = String(number); - while (str.length < length) { - str = '0' + str; - } - return str; + var str = String(number); + while (str.length < length) { + str = '0' + str; + } + return str; }; const padRight = (number, length) => { - var str = String(number); - while (str.length < length) { - str += '0'; - } - return str; + var str = String(number); + while (str.length < length) { + str += '0'; + } + return str; }; const fromTokenDecimals = (value, decimals) => { - value = numberToBN(value); - const pow = new BN(10, 10).pow(numberToBN(decimals)); - const int = value.div(pow); - const dec = padLeft(value.mod(pow).toString(10), decimals).replace(/0+$/, ''); - return int.toString(10) + (dec !== "" ? "." + dec : ""); + value = numberToBN(value); + const pow = new BN(10, 10).pow(numberToBN(decimals)); + const int = value.div(pow); + const dec = padLeft(value.mod(pow).toString(10), decimals).replace(/0+$/, ''); + return int.toString(10) + (dec !== '' ? '.' + dec : ''); }; const toTokenDecimals = (value, decimals) => { - value = value.toString().split("."); - const pow = new BN(10, 10).pow(numberToBN(decimals)); - const int = numberToBN(value[0]).mul(pow); - const dec = numberToBN(padRight(value.length > 1 ? value[1] : 0, decimals)); - if(dec.toString(10).length > pow.toString(10).length) throw new Error("Too many decimal places"); - return int.add(dec).toString(10); + value = value.toString().split('.'); + const pow = new BN(10, 10).pow(numberToBN(decimals)); + const int = numberToBN(value[0]).mul(pow); + const dec = numberToBN(padRight(value.length > 1 ? value[1] : 0, decimals)); + if (dec.toString(10).length > pow.toString(10).length) throw new Error('Too many decimal places'); + return int.add(dec).toString(10); }; module.exports = { - fromTokenDecimals, - toTokenDecimals + fromTokenDecimals, + toTokenDecimals }; - diff --git a/package-lock.json b/package-lock.json index 8152002..8b53c11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -357,6 +357,83 @@ "@date-io/core": "^0.0.2" } }, + "@iamstarkov/listr-update-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz", + "integrity": "sha512-IJyxQWsYDEkf8C8QthBn5N8tIUR9V9je6j3sMIpAkonaadjbvxmRC6RAhpa3RKxndhNnU2M6iNbtJwd7usQYIA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, "@material-ui/core": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.6.1.tgz", @@ -471,6 +548,15 @@ } } }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, "@types/jss": { "version": "9.5.7", "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.7.tgz", @@ -503,9 +589,9 @@ } }, "acorn": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", - "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", "dev": true }, "acorn-jsx": { @@ -515,9 +601,9 @@ "dev": true }, "ajv": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", - "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -547,6 +633,12 @@ "color-convert": "^1.9.0" } }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -556,6 +648,24 @@ "sprintf-js": "~1.0.2" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", @@ -566,17 +676,56 @@ "es-abstract": "^1.7.0" } }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, "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 }, + "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.18.0", "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", @@ -639,6 +788,61 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "bignumber.js": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-5.0.0.tgz", @@ -664,24 +868,84 @@ "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": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "brcast": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.1.tgz", "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg==" }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "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": { - "callsites": "^0.2.0" + "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" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } } }, "callsites": { - "version": "0.2.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "chain-function": { @@ -711,17 +975,55 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, "classnames": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -731,12 +1033,152 @@ "restore-cursor": "^2.0.0" } }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -752,17 +1194,59 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "dev": true + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" }, + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -807,6 +1291,24 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -827,6 +1329,61 @@ "object-keys": "^1.0.12" } }, + "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" + } + } + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + } + }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -841,6 +1398,18 @@ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "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 + }, "encoding": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", @@ -849,17 +1418,36 @@ "iconv-lite": "~0.4.13" } }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" } }, "es-to-primitive": { @@ -880,9 +1468,9 @@ "dev": true }, "eslint": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.9.0.tgz", - "integrity": "sha512-g4KWpPdqN0nth+goDNICNXGfJF7nNnepthp46CAlJoJtC5K/cLu3NgCM3AHu1CkJ5Hzt9V0Y0PBAO6Ay/gGb+w==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.13.0.tgz", + "integrity": "sha512-nqD5WQMisciZC5EHZowejLKQjWGuFS5c70fxqSKlnDME+oz9zmE8KTlX+lHSg+/5wsC/kf9Q9eMkC8qS3oM2fg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -894,7 +1482,7 @@ "eslint-scope": "^4.0.0", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", + "espree": "^5.0.0", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", @@ -902,9 +1490,9 @@ "glob": "^7.1.2", "globals": "^11.7.0", "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", @@ -914,10 +1502,8 @@ "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", "regexpp": "^2.0.1", - "require-uncached": "^1.0.3", "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", @@ -926,14 +1512,24 @@ }, "dependencies": { "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -942,6 +1538,125 @@ } } }, + "eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, + "requires": { + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" + } + }, + "eslint-config-prettier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.0.0.tgz", + "integrity": "sha512-kWuiJxzV5NwOwZcpyozTzDT5KJhBw292bbYro9Is7BWnbNMg15Gmpluc1CTetiCatF8DRkNvgPAOaSyg+bYr3g==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-config-standard": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-module-utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, "eslint-plugin-babel": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz", @@ -951,17 +1666,144 @@ "eslint-rule-composer": "^0.3.0" } }, + "eslint-plugin-es": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "read-pkg-up": "^2.0.0", + "resolve": "^1.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz", + "integrity": "sha512-ZjOjbjEi6jd82rIpFSgagv4CHWzG9xsQAVp1ZPlhRnnYxcTgENUVBvhYmkQ7GvT1QFijUSo69RaiOJKhMu6i8w==", + "dev": true, + "requires": { + "eslint-plugin-es": "^1.3.1", + "eslint-utils": "^1.3.1", + "ignore": "^5.0.2", + "minimatch": "^3.0.4", + "resolve": "^1.8.1", + "semver": "^5.5.0" + }, + "dependencies": { + "ignore": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.5.tgz", + "integrity": "sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", + "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-promise": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", + "dev": true + }, "eslint-plugin-react": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", - "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", + "version": "7.12.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz", + "integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==", "dev": true, "requires": { "array-includes": "^3.0.3", "doctrine": "^2.1.0", "has": "^1.0.3", "jsx-ast-utils": "^2.0.1", - "prop-types": "^15.6.2" + "object.fromentries": "^2.0.0", + "prop-types": "^15.6.2", + "resolve": "^1.9.0" + } + }, + "eslint-plugin-standard": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", + "dev": true + }, + "eslint-plugin-unicorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-7.1.0.tgz", + "integrity": "sha512-lW/ZwGR638V0XuZgR160qVQvPtw8tw3laKT5LjJPt+W+tN7kVf2S2V7x+ZrEEwSjEb3OiEzb3cppzaKuYtgYeg==", + "dev": true, + "requires": { + "clean-regexp": "^1.0.0", + "eslint-ast-utils": "^1.0.0", + "import-modules": "^1.1.0", + "lodash.camelcase": "^4.1.1", + "lodash.kebabcase": "^4.0.1", + "lodash.snakecase": "^4.0.1", + "lodash.upperfirst": "^4.2.0", + "safe-regex": "^2.0.1" + }, + "dependencies": { + "safe-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.0.1.tgz", + "integrity": "sha512-4tbOl0xq/cxbhEhdvxKaCZgzwOKeqt2tnHc2OPBkMsVdZ0s0C5oJwI6voRI9XzPSzeN35PECDNDK946x4d/0eA==", + "dev": true, + "requires": { + "regexp-tree": "~0.0.85" + } + } } }, "eslint-rule-composer": { @@ -993,9 +1835,9 @@ "dev": true }, "espree": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", - "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz", + "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==", "dev": true, "requires": { "acorn": "^6.0.2", @@ -1039,6 +1881,86 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, "external-editor": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", @@ -1050,12 +1972,83 @@ "tmp": "^0.0.33" } }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "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.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -1101,6 +2094,44 @@ "object-assign": "^4.0.1" } }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", @@ -1113,6 +2144,12 @@ "write": "^0.2.1" } }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, "follow-redirects": { "version": "1.5.8", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", @@ -1121,6 +2158,12 @@ "debug": "=3.1.0" } }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, "formik": { "version": "0.11.11", "resolved": "http://registry.npmjs.org/formik/-/formik-0.11.11.tgz", @@ -1143,6 +2186,15 @@ } } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1161,6 +2213,50 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "g-status": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", + "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "matcher": "^1.0.0", + "simple-git": "^1.85.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", + "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "dev": true + }, + "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-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -1181,6 +2277,27 @@ "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", "dev": true }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", @@ -1196,6 +2313,23 @@ "function-bind": "^1.1.1" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1208,6 +2342,38 @@ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "history": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", @@ -1235,6 +2401,30 @@ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "husky": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", + "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.7", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^6.0.0", + "is-ci": "^2.0.0", + "pkg-dir": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^4.0.1", + "run-node": "^1.0.0", + "slash": "^2.0.0" + } + }, "hyphenate-style-name": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz", @@ -1254,6 +2444,39 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "import-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-1.1.0.tgz", + "integrity": "sha1-dI23nFzEK7lwHvq0JPiU5yYA6dw=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1275,6 +2498,12 @@ } } }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1292,32 +2521,58 @@ "dev": true }, "inquirer": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", - "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^3.0.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^6.1.0", + "rxjs": "^6.4.0", "string-width": "^2.1.0", "strip-ansi": "^5.0.0", "through": "^2.3.6" }, "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", "dev": true }, + "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" + } + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "strip-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", @@ -1337,6 +2592,38 @@ "loose-envify": "^1.0.0" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "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": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -1348,18 +2635,93 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", @@ -1370,6 +2732,73 @@ "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1393,10 +2822,10 @@ "has": "^1.0.1" } }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, "is-stream": { @@ -1413,6 +2842,12 @@ "has-symbols": "^1.0.0" } }, + "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 + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -1464,6 +2899,12 @@ "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", "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", @@ -1564,6 +3005,21 @@ "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -1574,26 +3030,282 @@ "type-check": "~0.3.2" } }, + "lint-staged": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.3.tgz", + "integrity": "sha512-6TGkikL1B+6mIOuSNq2TV6oP21IhPMnV8q0cf9oYZ296ArTVNcbFh1l1pfVOHHbBIYLlziWNsQ2q45/ffmJ4AA==", + "dev": true, + "requires": { + "@iamstarkov/listr-update-renderer": "0.4.1", + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.0.2", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "del": "^3.0.0", + "execa": "^1.0.0", + "find-parent-dir": "^0.3.0", + "g-status": "^2.0.2", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "listr": "^0.14.2", + "lodash": "^4.17.5", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.2", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2", + "yup": "^0.26.10" + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", + "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + } + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=", + "dev": true + }, "lodash.topath": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" }, + "lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=", + "dev": true + }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -1602,6 +3314,40 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.4" + } + }, "material-ui-pickers": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/material-ui-pickers/-/material-ui-pickers-2.0.4.tgz", @@ -1615,6 +3361,36 @@ "tslib": "^1.9.3" } }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -1636,6 +3412,27 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -1656,6 +3453,25 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "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", @@ -1677,11 +3493,58 @@ "is-stream": "^1.0.1" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "normalize-scroll-left": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz", "integrity": "sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg==" }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -1703,12 +3566,73 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", "dev": true }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1741,12 +3665,124 @@ "wordwrap": "~1.0.0" } }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1765,6 +3801,12 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", @@ -1773,23 +3815,94 @@ "isarray": "0.0.1" } }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "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" + } + }, + "please-upgrade-node": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", + "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "popper.js": { "version": "1.14.6", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz", "integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA==" }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prettier": { + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "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" + } + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -1813,6 +3926,28 @@ "object-assign": "^4.1.1" } }, + "property-expr": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", + "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "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" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2036,6 +4171,83 @@ "react-lifecycles-compat": "^3.0.4" } }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + } + } + }, "recompose": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz", @@ -2054,26 +4266,70 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" }, + "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-tree": { + "version": "0.0.86", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.0.86.tgz", + "integrity": "sha512-xjTX9GmRw7Nn2wxinLoqQXv9Dt5yerP7CJIsYe/5z5gFs0Ltu20wRuZophafi9sf0JpsdVtki5EuICRYpgB1AQ==", + "dev": true, + "requires": { + "cli-table3": "^0.5.0", + "colors": "^1.1.2", + "yargs": "^10.0.3" + } + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, - "require-uncached": { - "version": "1.0.3", - "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "path-parse": "^1.0.6" } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "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-pathname": { @@ -2081,6 +4337,12 @@ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -2091,6 +4353,12 @@ "signal-exit": "^3.0.2" } }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -2117,6 +4385,12 @@ "is-promise": "^2.1.0" } }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, "rxjs": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", @@ -2131,6 +4405,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2150,6 +4433,41 @@ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -2176,10 +4494,42 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "slice-ansi": { + "simple-git": { + "version": "1.107.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.107.0.tgz", + "integrity": "sha512-t4OK1JRlp4ayKRfcW6owrWcRVLyHRUlhGd0uN6ZZTqfDq8a5XpcUdOKiGRNobHEuMtNqzp0vcJNvhYWwh5PsQA==", + "dev": true, + "requires": { + "debug": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 + } + } + }, + "slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz", - "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==", + "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", @@ -2187,18 +4537,227 @@ "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "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": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "staged-git-files": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", + "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2209,6 +4768,17 @@ "strip-ansi": "^4.0.0" } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2218,6 +4788,18 @@ "ansi-regex": "^3.0.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -2246,16 +4828,50 @@ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" }, + "synchronous-promise": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.6.tgz", + "integrity": "sha512-TyOuWLwkmtPL49LHCX1caIwHjRzcVd62+GF6h8W/jHOeZUFHpnd2XJDVuUlaTaLPH1nuu2M69mfHr5XbQJnf/g==", + "dev": true + }, "table": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz", - "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "dev": true, "requires": { - "ajv": "^6.6.1", + "ajv": "^6.9.1", "lodash": "^4.17.11", - "slice-ansi": "2.0.0", - "string-width": "^2.1.1" + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "text-table": { @@ -2285,6 +4901,54 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -2310,6 +4974,87 @@ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -2319,6 +5064,28 @@ "punycode": "^2.1.0" } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "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 + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "value-equal": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", @@ -2346,12 +5113,28 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2366,6 +5149,106 @@ "requires": { "mkdirp": "^0.5.1" } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + }, + "yup": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.26.10.tgz", + "integrity": "sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw==", + "dev": true, + "requires": { + "@babel/runtime": "7.0.0", + "fn-name": "~2.0.1", + "lodash": "^4.17.10", + "property-expr": "^1.5.0", + "synchronous-promise": "^2.0.5", + "toposort": "^2.0.2" + } } } } diff --git a/package.json b/package.json index 456ed97..0b23cbe 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "scripts": { "solidity-coverage": "./node_modules/.bin/solidity-coverage", "lint": "./node_modules/.bin/eslint app", - "test": "embark test" + "test": "embark test", + "precommit": "lint-staged", + "format": "prettier --write \"app/**/*.js\"" }, "repository": { "type": "git", @@ -17,6 +19,12 @@ "url": "https://github.com/status-im/contracts/issues" }, "homepage": "https://github.com/status-im/contracts#readme", + "lint-staged": { + "app/**/*.{js,json,css,md}": [ + "prettier --write", + "git add" + ] + }, "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-decorators": "^7.0.0", @@ -30,8 +38,19 @@ "@babel/plugin-syntax-import-meta": "^7.0.0", "babel-eslint": "^10.0.1", "eslint": "^5.9.0", + "eslint-config-prettier": "^4.0.0", + "eslint-config-standard": "^12.0.0", "eslint-plugin-babel": "^5.3.0", - "eslint-plugin-react": "^7.11.1" + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-node": "^8.0.1", + "eslint-plugin-prettier": "^3.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-react": "^7.12.4", + "eslint-plugin-standard": "^4.0.0", + "eslint-plugin-unicorn": "^7.1.0", + "husky": "^1.3.1", + "lint-staged": "^8.1.3", + "prettier": "^1.16.4" }, "dependencies": { "@date-io/date-fns": "0.0.2",