mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-30 12:18:09 +00:00
merge master
This commit is contained in:
commit
dce912226b
31
.babelrc
31
.babelrc
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
["env", {
|
|
||||||
"useBuiltIns": true,
|
|
||||||
"loose": true
|
|
||||||
}],
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"react-hot-loader/babel",
|
|
||||||
"transform-class-properties",
|
|
||||||
"transform-object-rest-spread",
|
|
||||||
"transform-flow-strip-types",
|
|
||||||
["transform-runtime", {
|
|
||||||
"polyfill": false,
|
|
||||||
"regenerator": true
|
|
||||||
}],
|
|
||||||
["module-resolver", {
|
|
||||||
"root": ["./src"],
|
|
||||||
"alias": {
|
|
||||||
"public": ["./public"]
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"babel-plugin-styled-components"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"test": {
|
|
||||||
"presets": ["jest"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
14
.eslintrc
14
.eslintrc
@ -10,7 +10,8 @@
|
|||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"jest": true
|
"jest": true,
|
||||||
|
"cypress/globals": true
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/prefer-default-export": 0,
|
"import/prefer-default-export": 0,
|
||||||
@ -32,13 +33,17 @@
|
|||||||
"new-cap": 0,
|
"new-cap": 0,
|
||||||
"max-len": 0,
|
"max-len": 0,
|
||||||
"eol-last": 0,
|
"eol-last": 0,
|
||||||
"spaced-comment": 0
|
"spaced-comment": 0,
|
||||||
|
"no-unused-expressions": 0,
|
||||||
|
"chai-friendly/no-unused-expressions": 2
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"import",
|
"import",
|
||||||
"react",
|
"react",
|
||||||
"jest",
|
"jest",
|
||||||
"flowtype"
|
"flowtype",
|
||||||
|
"cypress",
|
||||||
|
"chai-friendly"
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
@ -52,8 +57,7 @@
|
|||||||
"ecmaVersion": 7,
|
"ecmaVersion": 7,
|
||||||
"sourceType": "module",
|
"sourceType": "module",
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true,
|
"jsx": true
|
||||||
"experimentalObjectRestSpread": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
.*/_old/.*
|
.*/_old/.*
|
||||||
.*/scripts/solidity/.*
|
.*/scripts/solidity/.*
|
||||||
.*/build/.*
|
.*/build/.*
|
||||||
|
.*/cache/.*
|
||||||
|
|
||||||
[libs]
|
[libs]
|
||||||
./src/flowtype/npm/redux_v3.x.x.js
|
./src/flowtype/npm/redux_v3.x.x.js
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -19,4 +19,6 @@ logs
|
|||||||
|
|
||||||
_old
|
_old
|
||||||
|
|
||||||
coverage
|
coverage
|
||||||
|
test/**/__diff_output__
|
||||||
|
test/screenshots
|
@ -1,14 +1,19 @@
|
|||||||
image: node:9.3
|
image: node:10.15.1
|
||||||
|
|
||||||
|
variables:
|
||||||
|
CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/cache/Cypress"
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
paths:
|
paths:
|
||||||
- node_modules/
|
- node_modules
|
||||||
|
- ${CYPRESS_CACHE_FOLDER}
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- test
|
- test
|
||||||
- build
|
- build
|
||||||
- deploy
|
- deploy
|
||||||
|
- integration tests
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
stage: test
|
stage: test
|
||||||
@ -62,7 +67,23 @@ build stable:
|
|||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
paths:
|
paths:
|
||||||
- build/stable
|
- build/stable
|
||||||
- scripts/s3sync.sh
|
- scripts/s3sync.sh
|
||||||
|
|
||||||
|
build emulator and bridge image:
|
||||||
|
variables:
|
||||||
|
CONTAINER_NAME: "$CI_REGISTRY/emulator-bridge-tests"
|
||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
before_script:
|
||||||
|
- docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
|
||||||
|
stage: build
|
||||||
|
when: manual
|
||||||
|
script:
|
||||||
|
- docker pull $CONTAINER_NAME:latest || true
|
||||||
|
- docker build --cache-from $CONTAINER_NAME:latest --tag $CONTAINER_NAME:$CI_COMMIT_SHA --tag $CONTAINER_NAME:latest .
|
||||||
|
- docker push $CONTAINER_NAME:$CI_COMMIT_SHA
|
||||||
|
- docker push $CONTAINER_NAME:latest
|
||||||
|
|
||||||
deploy review:
|
deploy review:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
@ -138,3 +159,24 @@ delete review:
|
|||||||
- branches
|
- branches
|
||||||
tags:
|
tags:
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
|
integration tests:
|
||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
stage: integration tests
|
||||||
|
script:
|
||||||
|
- 'export SHARED_PATH="$(dirname ${CI_PROJECT_DIR})/shared"'
|
||||||
|
- rm -r ${SHARED_PATH} || true
|
||||||
|
- docker build -t wallet-emulator-bridge-tests .
|
||||||
|
- mkdir -p ${SHARED_PATH}/trezor-wallet/screenshots
|
||||||
|
- mkdir -p ${SHARED_PATH}/trezor-wallet/videos
|
||||||
|
- docker run --volume ${SHARED_PATH}/trezor-wallet/screenshots:/trezor-wallet/test/screenshots --volume ${SHARED_PATH}/trezor-wallet/videos:/trezor-wallet/test/videos --rm wallet-emulator-bridge-tests
|
||||||
|
- find ${SHARED_PATH}
|
||||||
|
- mkdir trezor-wallet
|
||||||
|
- cp -r ${SHARED_PATH}/ trezor-wallet/
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- trezor-wallet/
|
53
Dockerfile
53
Dockerfile
@ -1,17 +1,50 @@
|
|||||||
FROM node:9.3
|
FROM python:latest
|
||||||
|
|
||||||
ARG BUILD_TYPE=stable
|
#
|
||||||
|
# setup
|
||||||
|
#
|
||||||
|
RUN apt-get update
|
||||||
|
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||||
|
RUN apt-get install -y chromium libappindicator3-1 xdg-utils fonts-liberation nodejs wget dpkg git python python3 python3-pip xvfb libgtk2.0-0 libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2
|
||||||
|
RUN npm install -g yarn
|
||||||
|
|
||||||
WORKDIR /trezor-wallet-app
|
RUN ln -s /usr/bin/chromium /usr/local/bin/chromium-browser
|
||||||
|
|
||||||
COPY package.json /trezor-wallet-app
|
#
|
||||||
COPY yarn.lock /trezor-wallet-app
|
# build emulator
|
||||||
|
#
|
||||||
|
RUN mkdir /trezor-emulator
|
||||||
|
WORKDIR /trezor-emulator
|
||||||
|
|
||||||
RUN yarn install
|
RUN git clone https://github.com/trezor/trezor-core
|
||||||
|
WORKDIR /trezor-emulator/trezor-core
|
||||||
|
RUN git submodule update --init --recursive
|
||||||
|
|
||||||
COPY . /trezor-wallet-app
|
RUN apt-get install libusb-1.0-0
|
||||||
|
RUN pip3 install scons trezor
|
||||||
|
RUN make build_unix_noui
|
||||||
|
|
||||||
RUN yarn run build:${BUILD_TYPE}
|
#
|
||||||
|
# install bridge
|
||||||
|
#
|
||||||
|
RUN mkdir /trezor-bridge
|
||||||
|
WORKDIR /trezor-bridge
|
||||||
|
RUN wget https://wallet.trezor.io/data/bridge/2.0.25/trezor-bridge_2.0.25_amd64.deb
|
||||||
|
RUN dpkg -x /trezor-bridge/trezor-bridge_2.0.25_amd64.deb /trezor-bridge/extracted
|
||||||
|
|
||||||
EXPOSE 8080
|
#
|
||||||
CMD [ "yarn", "run", "prod-server" ]
|
# install trezor-wallet
|
||||||
|
#
|
||||||
|
RUN mkdir /trezor-wallet
|
||||||
|
WORKDIR /trezor-wallet
|
||||||
|
COPY package.json /trezor-wallet
|
||||||
|
COPY yarn.lock /trezor-wallet
|
||||||
|
RUN yarn
|
||||||
|
COPY . /trezor-wallet
|
||||||
|
RUN yarn run build:stable
|
||||||
|
|
||||||
|
#
|
||||||
|
# run
|
||||||
|
#
|
||||||
|
ENTRYPOINT ["/trezor-wallet/test/scripts/run-all.sh"]
|
||||||
|
EXPOSE 8080 21325
|
51
babel.config.js
Normal file
51
babel.config.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module.exports = (api) => {
|
||||||
|
// api.cache.forever();
|
||||||
|
|
||||||
|
const presets = [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
useBuiltIns: 'entry',
|
||||||
|
loose: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@babel/preset-react',
|
||||||
|
'@babel/preset-flow',
|
||||||
|
];
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
'react-hot-loader/babel',
|
||||||
|
'@babel/plugin-transform-flow-strip-types',
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
|
'@babel/plugin-proposal-object-rest-spread',
|
||||||
|
[
|
||||||
|
'@babel/plugin-transform-runtime',
|
||||||
|
{
|
||||||
|
regenerator: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'module-resolver',
|
||||||
|
{
|
||||||
|
root: [
|
||||||
|
'./src',
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
public: [
|
||||||
|
'./public',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'babel-plugin-styled-components',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (api.env('test')) {
|
||||||
|
presets.push('jest');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
presets,
|
||||||
|
plugins,
|
||||||
|
};
|
||||||
|
};
|
11
cypress.json
Normal file
11
cypress.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"integrationFolder": "test/integration",
|
||||||
|
"fixturesFolder": "test/fixtures",
|
||||||
|
"pluginsFile": "test/plugins/index.js",
|
||||||
|
"supportFile": "test/support/index.js",
|
||||||
|
"defaultCommandTimeout": 10000,
|
||||||
|
"screenshotsFolder": "test/screenshots",
|
||||||
|
"video": false,
|
||||||
|
"trashAssetsBeforeRuns": true,
|
||||||
|
"chromeWebSecurity": false
|
||||||
|
}
|
@ -17,4 +17,7 @@ module.exports = {
|
|||||||
setupFiles: [
|
setupFiles: [
|
||||||
'./support/setupJest.js',
|
'./support/setupJest.js',
|
||||||
],
|
],
|
||||||
|
transform: {
|
||||||
|
'^.+\\.jsx?$': 'babel-jest',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
124
package.json
124
package.json
@ -21,24 +21,25 @@
|
|||||||
"test": "run-s test:*",
|
"test": "run-s test:*",
|
||||||
"test:unit": "npx jest",
|
"test:unit": "npx jest",
|
||||||
"test-unit:watch": "npx jest -o --watch",
|
"test-unit:watch": "npx jest -o --watch",
|
||||||
|
"test-integration:dev": "npx cypress open -c baseUrl=http://localhost:8081/#/",
|
||||||
|
"test-integration:test": "npx cypress run",
|
||||||
|
"test-integration:gitlab": "npx cypress run -c baseUrl=https://localhost:8080/#/ --browser chromium",
|
||||||
"server:beta": "node ./server/index.js --buildType=beta",
|
"server:beta": "node ./server/index.js --buildType=beta",
|
||||||
"server:stable": "node ./server/index.js --buildType=stable"
|
"server:stable": "node ./server/index.js --buildType=stable"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel": "^6.23.0",
|
"@babel/polyfill": "^7.2.5",
|
||||||
"babel-core": "^6.26.3",
|
|
||||||
"bignumber.js": "2.4.0",
|
"bignumber.js": "2.4.0",
|
||||||
"color-hash": "^1.0.3",
|
"color-hash": "^1.0.3",
|
||||||
"commander": "^2.19.0",
|
"commander": "^2.19.0",
|
||||||
"connected-react-router": "^6.0.0",
|
"connected-react-router": "^6.2.2",
|
||||||
"copy-webpack-plugin": "^4.5.2",
|
"copy-webpack-plugin": "^4.6.0",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.30.1",
|
||||||
"ethereumjs-tx": "^1.3.3",
|
"ethereumjs-tx": "^1.3.7",
|
||||||
"ethereumjs-units": "^0.2.0",
|
"ethereumjs-units": "^0.2.0",
|
||||||
"ethereumjs-util": "^5.1.4",
|
"ethereumjs-util": "^5.2.0",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.4",
|
||||||
"flow-webpack-plugin": "^1.2.0",
|
|
||||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||||
"git-revision-webpack-plugin": "^3.0.3",
|
"git-revision-webpack-plugin": "^3.0.3",
|
||||||
"hdkey": "^0.8.0",
|
"hdkey": "^0.8.0",
|
||||||
@ -46,78 +47,87 @@
|
|||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"jest-fetch-mock": "^1.6.5",
|
"jest-fetch-mock": "^1.6.5",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
"npm-run-all": "^4.1.3",
|
"npm-run-all": "^4.1.5",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"raf": "^3.4.0",
|
|
||||||
"raven-js": "^3.22.3",
|
|
||||||
"rc-tooltip": "^3.7.0",
|
|
||||||
"react": "^16.6.3",
|
|
||||||
"react-dom": "^16.6.3",
|
|
||||||
"react-hot-loader": "^4.6.2",
|
|
||||||
"react-intl": "^2.8.0",
|
"react-intl": "^2.8.0",
|
||||||
|
"raf": "^3.4.1",
|
||||||
|
"raven-js": "^3.27.0",
|
||||||
|
"rc-tooltip": "^3.7.3",
|
||||||
|
"react": "^16.7.0",
|
||||||
|
"react-dom": "^16.7.0",
|
||||||
|
"react-hot-loader": "^4.6.5",
|
||||||
"react-json-view": "^1.19.1",
|
"react-json-view": "^1.19.1",
|
||||||
"react-qr-reader": "^2.1.2",
|
"react-qr-reader": "^2.1.2",
|
||||||
"react-qr-svg": "^2.1.0",
|
"react-qr-svg": "^2.1.0",
|
||||||
"react-redux": "^6.0.0",
|
"react-redux": "^6.0.0",
|
||||||
"react-router": "^4.3.1",
|
"react-router": "^4.3.1",
|
||||||
"react-router-dom": "^4.2.2",
|
"react-router-dom": "^4.3.1",
|
||||||
"react-scale-text": "^1.2.2",
|
"react-scale-text": "^1.2.2",
|
||||||
"react-select": "^2.2.0",
|
"react-select": "^2.3.0",
|
||||||
"react-textarea-autosize": "^7.0.4",
|
"react-textarea-autosize": "^7.1.0",
|
||||||
"react-transition-group": "^2.4.0",
|
"react-transition-group": "^2.5.3",
|
||||||
"redbox-react": "^1.6.0",
|
"redbox-react": "^1.6.0",
|
||||||
"redux": "4.0.0",
|
"redux": "4.0.1",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"redux-raven-middleware": "^1.2.0",
|
"redux-raven-middleware": "^1.2.0",
|
||||||
"redux-thunk": "^2.2.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"rimraf": "^2.6.2",
|
"request": "^2.88.0",
|
||||||
"styled-components": "^4.1.2",
|
"rimraf": "^2.6.3",
|
||||||
"styled-normalize": "^8.0.4",
|
"styled-components": "^4.1.3",
|
||||||
|
"styled-normalize": "^8.0.6",
|
||||||
|
"trezor-bridge-communicator": "1.0.2",
|
||||||
"trezor-connect": "7.0.0-beta.2",
|
"trezor-connect": "7.0.0-beta.2",
|
||||||
"wallet-address-validator": "^0.2.4",
|
"wallet-address-validator": "^0.2.4",
|
||||||
"web3": "1.0.0-beta.35",
|
"web3": "1.0.0-beta.35",
|
||||||
"webpack": "^4.16.3",
|
"webpack": "^4.29.1",
|
||||||
"webpack-build-notifier": "^0.1.29",
|
"webpack-build-notifier": "^0.1.30",
|
||||||
"webpack-bundle-analyzer": "^2.13.1",
|
"webpack-bundle-analyzer": "^3.0.3",
|
||||||
"whatwg-fetch": "^2.0.4",
|
"whatwg-fetch": "^2.0.4",
|
||||||
"yarn-run-all": "^3.1.1"
|
"yarn-run-all": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-cli": "^6.24.1",
|
"@babel/cli": "^7.2.3",
|
||||||
"babel-eslint": "^8.2.6",
|
"@babel/core": "^7.2.2",
|
||||||
"babel-loader": "^7.1.5",
|
"@babel/plugin-proposal-class-properties": "^7.3.0",
|
||||||
"babel-plugin-module-resolver": "^3.1.1",
|
"@babel/plugin-proposal-object-rest-spread": "^7.3.2",
|
||||||
"babel-plugin-styled-components": "^1.5.1",
|
"@babel/plugin-transform-flow-strip-types": "^7.2.3",
|
||||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
"@babel/plugin-transform-runtime": "^7.2.0",
|
||||||
"babel-plugin-transform-flow-strip-types": "^6.22.0",
|
"@babel/preset-env": "^7.3.1",
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.23.0",
|
"@babel/preset-flow": "^7.0.0",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"babel-preset-env": "^1.6.0",
|
"@babel/register": "^7.0.0",
|
||||||
"babel-preset-jest": "^23.2.0",
|
"babel-eslint": "^10.0.1",
|
||||||
"babel-preset-react": "^6.24.1",
|
"babel-jest": "^24.1.0",
|
||||||
"eslint": "^4",
|
"babel-loader": "^8.0.5",
|
||||||
"eslint-config-airbnb": "^17.0.0",
|
"babel-plugin-module-resolver": "^3.1.3",
|
||||||
"eslint-import-resolver-babel-module": "^4.0.0",
|
"babel-plugin-styled-components": "^1.10.0",
|
||||||
"eslint-loader": "^2.1.0",
|
"cypress": "^3.1.5",
|
||||||
"eslint-plugin-flowtype": "^2.50.0",
|
"cypress-image-snapshot": "^3.0.0",
|
||||||
"eslint-plugin-import": "^2.14.0",
|
"eslint": "^5.13.0",
|
||||||
"eslint-plugin-jest": "^21.18.0",
|
"eslint-config-airbnb": "^17.1.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.1.1",
|
"eslint-import-resolver-babel-module": "^5.0.1",
|
||||||
"eslint-plugin-react": "^7.10.0",
|
"eslint-loader": "^2.1.2",
|
||||||
"file-loader": "1.1.11",
|
"eslint-plugin-chai-friendly": "^0.4.1",
|
||||||
|
"eslint-plugin-cypress": "^2.2.0",
|
||||||
|
"eslint-plugin-flowtype": "^3.2.1",
|
||||||
|
"eslint-plugin-import": "^2.16.0",
|
||||||
|
"eslint-plugin-jest": "^22.2.2",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.2.1",
|
||||||
|
"eslint-plugin-react": "^7.12.4",
|
||||||
|
"file-loader": "3.0.1",
|
||||||
"flow-bin": "0.75.0",
|
"flow-bin": "0.75.0",
|
||||||
"jest": "^23.4.2",
|
"jest": "^24.1.0",
|
||||||
"stylelint": "^8.0.0",
|
"stylelint": "^9.10.1",
|
||||||
"stylelint-config-standard": "^18.2.0",
|
"stylelint-config-standard": "^18.2.0",
|
||||||
"stylelint-config-styled-components": "^0.1.1",
|
"stylelint-config-styled-components": "^0.1.1",
|
||||||
"stylelint-custom-processor-loader": "^0.5.0",
|
"stylelint-custom-processor-loader": "^0.6.0",
|
||||||
"stylelint-processor-styled-components": "^1.3.2",
|
"stylelint-processor-styled-components": "^1.5.2",
|
||||||
"stylelint-webpack-plugin": "^0.10.5",
|
"stylelint-webpack-plugin": "^0.10.5",
|
||||||
"webpack-cli": "^2.1.3",
|
"webpack-cli": "^3.2.3",
|
||||||
"webpack-dev-server": "^3.1.4",
|
"webpack-dev-server": "^3.1.14",
|
||||||
"yargs": "11.0.0"
|
"yargs": "11.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "*"
|
"fsevents": "1.2.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ type Props = {
|
|||||||
isWhite?: boolean,
|
isWhite?: boolean,
|
||||||
isWebUsb?: boolean,
|
isWebUsb?: boolean,
|
||||||
isTransparent?: boolean,
|
isTransparent?: boolean,
|
||||||
|
dataTest?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Wrapper = styled.button`
|
const Wrapper = styled.button`
|
||||||
@ -146,10 +147,12 @@ const Button = ({
|
|||||||
isWhite = false,
|
isWhite = false,
|
||||||
isWebUsb = false,
|
isWebUsb = false,
|
||||||
isTransparent = false,
|
isTransparent = false,
|
||||||
|
dataTest,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className;
|
const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className;
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
data-test={dataTest}
|
||||||
className={newClassName}
|
className={newClassName}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
@ -176,6 +179,7 @@ Button.propTypes = {
|
|||||||
isWhite: PropTypes.bool,
|
isWhite: PropTypes.bool,
|
||||||
isWebUsb: PropTypes.bool,
|
isWebUsb: PropTypes.bool,
|
||||||
isTransparent: PropTypes.bool,
|
isTransparent: PropTypes.bool,
|
||||||
|
dataTest: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Button;
|
export default Button;
|
@ -98,11 +98,13 @@ const DeviceHeader = ({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
className,
|
className,
|
||||||
|
testId,
|
||||||
}) => {
|
}) => {
|
||||||
const status = getStatus(device);
|
const status = getStatus(device);
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
|
data-test={testId}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
isHoverable={isHoverable}
|
isHoverable={isHoverable}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
@ -134,6 +136,7 @@ DeviceHeader.propTypes = {
|
|||||||
isSelected: PropTypes.bool,
|
isSelected: PropTypes.bool,
|
||||||
onClickWrapper: PropTypes.func.isRequired,
|
onClickWrapper: PropTypes.func.isRequired,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
testId: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeviceHeader;
|
export default DeviceHeader;
|
||||||
|
@ -124,7 +124,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Header = ({ sidebarEnabled, sidebarOpened, toggleSidebar }: Props) => (
|
const Header = ({ sidebarEnabled, sidebarOpened, toggleSidebar }: Props) => (
|
||||||
<Wrapper>
|
<Wrapper data-test="Main__page__navigation">
|
||||||
<LayoutWrapper>
|
<LayoutWrapper>
|
||||||
<Left>
|
<Left>
|
||||||
{ sidebarEnabled && <MenuToggler onClick={toggleSidebar}>{sidebarOpened ? '✕ Close' : '☰ Menu'}</MenuToggler>}
|
{ sidebarEnabled && <MenuToggler onClick={toggleSidebar}>{sidebarOpened ? '✕ Close' : '☰ Menu'}</MenuToggler>}
|
||||||
|
@ -31,11 +31,13 @@ const Tooltip = ({
|
|||||||
content,
|
content,
|
||||||
readMoreLink,
|
readMoreLink,
|
||||||
children,
|
children,
|
||||||
|
enterDelayMs,
|
||||||
}) => (
|
}) => (
|
||||||
<Wrapper className={className}>
|
<Wrapper className={className}>
|
||||||
<RcTooltip
|
<RcTooltip
|
||||||
arrowContent={<div className="rc-tooltip-arrow-inner" />}
|
arrowContent={<div className="rc-tooltip-arrow-inner" />}
|
||||||
placement={placement}
|
placement={placement}
|
||||||
|
mouseEnterDelay={enterDelayMs || 0}
|
||||||
overlay={() => (
|
overlay={() => (
|
||||||
<ContentWrapper>
|
<ContentWrapper>
|
||||||
<Content maxWidth={maxWidth}>{content}</Content>
|
<Content maxWidth={maxWidth}>{content}</Content>
|
||||||
@ -45,7 +47,8 @@ const Tooltip = ({
|
|||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</ContentWrapper>)}
|
</ContentWrapper>
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</RcTooltip>
|
</RcTooltip>
|
||||||
@ -65,6 +68,7 @@ Tooltip.propTypes = {
|
|||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
]),
|
]),
|
||||||
readMoreLink: PropTypes.string,
|
readMoreLink: PropTypes.string,
|
||||||
|
enterDelayMs: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tooltip;
|
export default Tooltip;
|
||||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import ICONS from 'config/icons';
|
||||||
|
|
||||||
const SvgWrapper = styled.svg`
|
const SvgWrapper = styled.svg`
|
||||||
:hover {
|
:hover {
|
||||||
@ -15,9 +16,6 @@ const Path = styled.path`
|
|||||||
fill: ${props => props.color};
|
fill: ${props => props.color};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const HIDDEN = 'M25.421,17.28l-3.167-8.8C22.175,8.24,21.858,8,21.542,8h-2.375c-0.475,0-0.792,0.32-0.792,0.8c0,0.48,0.317,0.8,0.792,0.8h1.821l2.612,7.2h-6.017h-3.167H8.4l2.613-7.2h1.821c0.475,0,0.792-0.32,0.792-0.8c0-0.48-0.317-0.8-0.792-0.8h-2.375c-0.317,0-0.633,0.24-0.712,0.56l-3.167,8.8C6.5,17.36,6.5,17.52,6.5,17.6l0,0l0,0l0,0v4c0,1.36,1.029,2.4,2.375,2.4h3.958c1.346,0,2.375-1.04,2.375-2.4v-3.2h1.583v3.2c0,1.36,1.029,2.4,2.375,2.4h3.958c1.346,0,2.375-1.04,2.375-2.4v-4l0,0l0,0l0,0C25.5,17.52,25.5,17.36,25.421,17.28z';
|
|
||||||
export const STANDARD = 'M23.333,10.667H10.667H10c-0.367,0-0.667-0.299-0.667-0.667S9.633,9.333,10,9.333h10V10h1.333V8.667C21.333,8.299,21.035,8,20.667,8H10c-1.105,0-2,0.895-2,2v11.333C8,22.806,9.194,24,10.667,24h12.667C23.701,24,24,23.701,24,23.333v-12C24,10.965,23.701,10.667,23.333,10.667z M20,18.667c-0.737,0-1.333-0.597-1.333-1.333C18.667,16.597,19.263,16,20,16s1.333,0.597,1.333,1.333C21.333,18.07,20.737,18.667,20,18.667z';
|
|
||||||
|
|
||||||
const Icon = ({
|
const Icon = ({
|
||||||
type = 'standard',
|
type = 'standard',
|
||||||
size = 24,
|
size = 24,
|
||||||
@ -29,13 +27,13 @@ const Icon = ({
|
|||||||
hoverColor={hoverColor}
|
hoverColor={hoverColor}
|
||||||
width={`${size}`}
|
width={`${size}`}
|
||||||
height={`${size}`}
|
height={`${size}`}
|
||||||
viewBox="0 0 32 32"
|
viewBox="0 0 1024 1024"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<Path
|
<Path
|
||||||
key={type}
|
key={type}
|
||||||
color={color}
|
color={color}
|
||||||
d={type === 'hidden' ? HIDDEN : STANDARD}
|
d={type === 'hidden' ? ICONS.WALLET_HIDDEN : ICONS.WALLET_STANDARD}
|
||||||
/>
|
/>
|
||||||
</SvgWrapper>
|
</SvgWrapper>
|
||||||
);
|
);
|
||||||
|
@ -127,7 +127,8 @@ class QrModal extends React.Component<Props, State> {
|
|||||||
{!this.state.readerLoaded && (
|
{!this.state.readerLoaded && (
|
||||||
<CameraPlaceholder>
|
<CameraPlaceholder>
|
||||||
Waiting for camera...
|
Waiting for camera...
|
||||||
</CameraPlaceholder>)
|
</CameraPlaceholder>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</Padding>
|
</Padding>
|
||||||
<StyledQrReader
|
<StyledQrReader
|
||||||
|
@ -68,7 +68,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
<Pin
|
<Pin
|
||||||
device={modal.device}
|
device={modal.device}
|
||||||
onPinSubmit={modalActions.onPinSubmit}
|
onPinSubmit={modalActions.onPinSubmit}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case UI.INVALID_PIN:
|
case UI.INVALID_PIN:
|
||||||
return <InvalidPin device={modal.device} />;
|
return <InvalidPin device={modal.device} />;
|
||||||
@ -79,7 +80,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
device={modal.device}
|
device={modal.device}
|
||||||
selectedDevice={props.wallet.selectedDevice}
|
selectedDevice={props.wallet.selectedDevice}
|
||||||
onPassphraseSubmit={modalActions.onPassphraseSubmit}
|
onPassphraseSubmit={modalActions.onPassphraseSubmit}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case 'ButtonRequest_PassphraseType':
|
case 'ButtonRequest_PassphraseType':
|
||||||
return <PassphraseType device={modal.device} />;
|
return <PassphraseType device={modal.device} />;
|
||||||
@ -110,7 +112,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
onCancel={modalActions.onCancel}
|
onCancel={modalActions.onCancel}
|
||||||
showAddress={props.receiveActions.showAddress}
|
showAddress={props.receiveActions.showAddress}
|
||||||
showUnverifiedAddress={props.receiveActions.showUnverifiedAddress}
|
showUnverifiedAddress={props.receiveActions.showUnverifiedAddress}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case CONNECT.REMEMBER_REQUEST:
|
case CONNECT.REMEMBER_REQUEST:
|
||||||
return (
|
return (
|
||||||
@ -119,7 +122,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
instances={modal.instances}
|
instances={modal.instances}
|
||||||
onRememberDevice={modalActions.onRememberDevice}
|
onRememberDevice={modalActions.onRememberDevice}
|
||||||
onForgetDevice={modalActions.onForgetDevice}
|
onForgetDevice={modalActions.onForgetDevice}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case CONNECT.FORGET_REQUEST:
|
case CONNECT.FORGET_REQUEST:
|
||||||
return (
|
return (
|
||||||
@ -127,7 +131,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
device={modal.device}
|
device={modal.device}
|
||||||
onForgetSingleDevice={modalActions.onForgetSingleDevice}
|
onForgetSingleDevice={modalActions.onForgetSingleDevice}
|
||||||
onCancel={modalActions.onCancel}
|
onCancel={modalActions.onCancel}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case CONNECT.TRY_TO_DUPLICATE:
|
case CONNECT.TRY_TO_DUPLICATE:
|
||||||
return (
|
return (
|
||||||
@ -136,7 +141,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
devices={props.devices}
|
devices={props.devices}
|
||||||
onDuplicateDevice={modalActions.onDuplicateDevice}
|
onDuplicateDevice={modalActions.onDuplicateDevice}
|
||||||
onCancel={modalActions.onCancel}
|
onCancel={modalActions.onCancel}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case CONNECT.REQUEST_WALLET_TYPE:
|
case CONNECT.REQUEST_WALLET_TYPE:
|
||||||
return (
|
return (
|
||||||
@ -144,7 +150,8 @@ const getDeviceContextModal = (props: Props) => {
|
|||||||
device={modal.device}
|
device={modal.device}
|
||||||
onWalletTypeRequest={modalActions.onWalletTypeRequest}
|
onWalletTypeRequest={modalActions.onWalletTypeRequest}
|
||||||
onCancel={modalActions.onCancel}
|
onCancel={modalActions.onCancel}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
@ -70,6 +70,12 @@ export default {
|
|||||||
SUCCESS: [
|
SUCCESS: [
|
||||||
'M692.8 313.92l-1.92-1.92c-6.246-7.057-15.326-11.484-25.44-11.484s-19.194 4.427-25.409 11.448l-0.031 0.036-196.48 224-3.84 1.6-3.84-1.92-48.64-57.28c-7.010-7.905-17.193-12.862-28.533-12.862-21.031 0-38.080 17.049-38.080 38.080 0 7.495 2.165 14.485 5.905 20.377l-0.092-0.155 100.8 148.16c5.391 8.036 14.386 13.292 24.618 13.44h8.662c17.251-0.146 32.385-9.075 41.163-22.529l0.117-0.191 195.2-296.32c4.473-6.632 7.141-14.803 7.141-23.597 0-11.162-4.297-21.32-11.326-28.911l0.025 0.028z',
|
'M692.8 313.92l-1.92-1.92c-6.246-7.057-15.326-11.484-25.44-11.484s-19.194 4.427-25.409 11.448l-0.031 0.036-196.48 224-3.84 1.6-3.84-1.92-48.64-57.28c-7.010-7.905-17.193-12.862-28.533-12.862-21.031 0-38.080 17.049-38.080 38.080 0 7.495 2.165 14.485 5.905 20.377l-0.092-0.155 100.8 148.16c5.391 8.036 14.386 13.292 24.618 13.44h8.662c17.251-0.146 32.385-9.075 41.163-22.529l0.117-0.191 195.2-296.32c4.473-6.632 7.141-14.803 7.141-23.597 0-11.162-4.297-21.32-11.326-28.911l0.025 0.028z',
|
||||||
],
|
],
|
||||||
|
WALLET_STANDARD: [
|
||||||
|
'M746.656,341.344l-405.312,0l-21.344,0c-11.744,0 -21.344,-9.568 -21.344,-21.344c0,-11.776 9.6,-21.344 21.344,-21.344l320,0l0,21.344l42.656,0l0,-42.656c0,-11.776 -9.536,-21.344 -21.312,-21.344l-341.344,0c-35.36,0 -64,28.64 -64,64l0,362.656c0,47.136 38.208,85.344 85.344,85.344l405.344,0c11.744,0 21.312,-9.568 21.312,-21.344l0,-384c0,-11.776 -9.568,-21.312 -21.344,-21.312Zm-106.656,256c-23.584,0 -42.656,-19.104 -42.656,-42.656c0,-23.584 19.072,-42.688 42.656,-42.688c23.584,0 42.656,19.104 42.656,42.656c0,23.584 -19.072,42.688 -42.656,42.688Z',
|
||||||
|
],
|
||||||
|
WALLET_HIDDEN: [
|
||||||
|
'M813.472,552.96l-101.344,-281.6c-2.528,-7.68 -12.672,-15.36 -22.784,-15.36l-76,0c-15.2,0 -25.344,10.24 -25.344,25.6c0,15.36 10.144,25.6 25.344,25.6l58.272,0l83.584,230.4l-192.544,0l-101.344,0l-192.512,0l83.616,-230.4l58.272,0c15.2,0 25.344,-10.24 25.344,-25.6c0,-15.36 -10.144,-25.6 -25.344,-25.6l-76,0c-10.144,0 -20.256,7.68 -22.784,17.92l-101.344,281.6c-2.56,0 -2.56,5.12 -2.56,7.68l0,128c0,43.52 32.928,76.8 76,76.8l126.656,0c43.072,0 76,-33.28 76,-76.8l0,-102.4l50.656,0l0,102.4c0,43.52 32.928,76.8 76,76.8l126.656,0c43.072,0 76,-33.28 76,-76.8l0,-128c0.032,-2.56 0.032,-7.68 -2.496,-10.24Z',
|
||||||
|
],
|
||||||
QRCODE: [
|
QRCODE: [
|
||||||
'M832 1024l-64 0l0 -128l64 0l0 128Zm-320 0l-64 0l0 -128l64 0l0 128Zm192 0l-128 0l0 -128l128 0l0 128Zm192 -192l64 0l0 64l64 0l0 128l-128 0l0 -192Zm-896 -192l384 0l0 384l-384 0l0 -384Zm320 320l0 -256l-256 0l0 256l256 0Zm-64 -64l-128 0l0 -128l128 0l0 128Zm512 0l-64 0l0 -64l64 0l0 64Zm-192 -128l0 128l-64 0l0 -64l-64 0l0 -64l128 0Zm128 64l-64 0l0 -64l64 0l0 64Zm192 0l-128 0l0 -64l128 0l0 64Zm-256 -64l-64 0l0 -64l64 0l0 64Zm320 -64l-64 0l0 -64l128 0l0 128l-64 0l0 -64Zm-384 0l-128 0l0 -128l128 0l0 128Zm64 -64l64 0l0 -64l128 0l0 128l-192 0l0 -64Zm-320 -128l64 0l0 -64l64 0l0 128l-128 0l0 -64Zm256 0l-64 0l0 -64l192 0l0 128l-128 0l0 -64Zm-576 -64l128 0l0 64l64 0l0 64l-192 0l0 -128Zm896 64l-128 0l0 -64l256 0l0 128l-128 0l0 -64Zm-576 0l-128 0l0 -64l128 0l0 64Zm192 -64l-64 0l0 -64l64 0l0 64Zm-512 -448l384 0l0 384l-384 0l0 -384Zm576 384l-64 0l0 -128l64 0l0 128Zm64 -384l384 0l0 384l-384 0l0 -384Zm-320 320l0 -256l-256 0l0 256l256 0Zm640 0l0 -256l-256 0l0 256l256 0Zm-704 -64l-128 0l0 -128l128 0l0 128Zm640 0l-128 0l0 -128l128 0l0 128Zm-384 -256l0 64l64 0l0 128l-64 0l0 64l-64 0l0 -256l64 0Z',
|
'M832 1024l-64 0l0 -128l64 0l0 128Zm-320 0l-64 0l0 -128l64 0l0 128Zm192 0l-128 0l0 -128l128 0l0 128Zm192 -192l64 0l0 64l64 0l0 128l-128 0l0 -192Zm-896 -192l384 0l0 384l-384 0l0 -384Zm320 320l0 -256l-256 0l0 256l256 0Zm-64 -64l-128 0l0 -128l128 0l0 128Zm512 0l-64 0l0 -64l64 0l0 64Zm-192 -128l0 128l-64 0l0 -64l-64 0l0 -64l128 0Zm128 64l-64 0l0 -64l64 0l0 64Zm192 0l-128 0l0 -64l128 0l0 64Zm-256 -64l-64 0l0 -64l64 0l0 64Zm320 -64l-64 0l0 -64l128 0l0 128l-64 0l0 -64Zm-384 0l-128 0l0 -128l128 0l0 128Zm64 -64l64 0l0 -64l128 0l0 128l-192 0l0 -64Zm-320 -128l64 0l0 -64l64 0l0 128l-128 0l0 -64Zm256 0l-64 0l0 -64l192 0l0 128l-128 0l0 -64Zm-576 -64l128 0l0 64l64 0l0 64l-192 0l0 -128Zm896 64l-128 0l0 -64l256 0l0 128l-128 0l0 -64Zm-576 0l-128 0l0 -64l128 0l0 64Zm192 -64l-64 0l0 -64l64 0l0 64Zm-512 -448l384 0l0 384l-384 0l0 -384Zm576 384l-64 0l0 -128l64 0l0 128Zm64 -384l384 0l0 384l-384 0l0 -384Zm-320 320l0 -256l-256 0l0 256l256 0Zm640 0l0 -256l-256 0l0 256l256 0Zm-704 -64l-128 0l0 -128l128 0l0 128Zm640 0l-128 0l0 -128l128 0l0 128Zm-384 -256l0 64l64 0l0 128l-64 0l0 64l-64 0l0 -256l64 0Z',
|
||||||
],
|
],
|
||||||
|
@ -92,8 +92,8 @@ export default (state: State = initialState, action: Action): State => {
|
|||||||
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA:
|
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA:
|
||||||
return clear(state, action.devices);
|
return clear(state, action.devices);
|
||||||
|
|
||||||
//case CONNECT.FORGET_SINGLE :
|
//case CONNECT.FORGET_SINGLE :
|
||||||
// return forgetAccounts(state, action);
|
// return forgetAccounts(state, action);
|
||||||
|
|
||||||
case ACCOUNT.UPDATE:
|
case ACCOUNT.UPDATE:
|
||||||
return updateAccount(state, action.payload);
|
return updateAccount(state, action.payload);
|
||||||
|
@ -17,7 +17,7 @@ import * as WalletActions from 'actions/WalletActions';
|
|||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
min-height: 100vh;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
background: rgba(0, 0, 0, 0.35);
|
background: rgba(0, 0, 0, 0.35);
|
||||||
@ -68,7 +68,7 @@ const BetaDisclaimer = (props: { close: () => void }) => (
|
|||||||
/>
|
/>
|
||||||
Please note that the <i>Trezor Beta Wallet</i> might be collecting anonymized usage data, especially error logs, for development purposes. The <i>Trezor Wallet</i> does not log any data.
|
Please note that the <i>Trezor Beta Wallet</i> might be collecting anonymized usage data, especially error logs, for development purposes. The <i>Trezor Wallet</i> does not log any data.
|
||||||
</StyledP>
|
</StyledP>
|
||||||
<StyledButton onClick={props.close}>OK, I understand</StyledButton>
|
<StyledButton dataTest="Modal__disclaimer__button__confirm" onClick={props.close}>OK, I understand</StyledButton>
|
||||||
</ModalWindow>
|
</ModalWindow>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
|
@ -57,7 +57,7 @@ class CoinMenu extends PureComponent<Props> {
|
|||||||
render() {
|
render() {
|
||||||
const { config } = this.props.localStorage;
|
const { config } = this.props.localStorage;
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper data-test="Main__page__coin__menu">
|
||||||
{config.networks.map(item => (
|
{config.networks.map(item => (
|
||||||
<NavLink
|
<NavLink
|
||||||
key={item.shortcut}
|
key={item.shortcut}
|
||||||
@ -72,6 +72,7 @@ class CoinMenu extends PureComponent<Props> {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
<Divider
|
<Divider
|
||||||
|
testId="Main__page__coin__menu__divider"
|
||||||
textLeft="Other coins"
|
textLeft="Other coins"
|
||||||
textRight="(You will be redirected)"
|
textRight="(You will be redirected)"
|
||||||
hasBorder
|
hasBorder
|
||||||
|
@ -30,19 +30,6 @@ const Label = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
class MenuItems extends PureComponent {
|
class MenuItems extends PureComponent {
|
||||||
onDeviceMenuClick(action, device) {
|
|
||||||
if (action === 'reload') {
|
|
||||||
this.props.acquireDevice();
|
|
||||||
} else if (action === 'forget') {
|
|
||||||
this.props.forgetDevice(device);
|
|
||||||
} else if (action === 'clone') {
|
|
||||||
this.props.duplicateDevice(device);
|
|
||||||
} else if (action === 'settings') {
|
|
||||||
this.props.toggleDeviceDropdown(false);
|
|
||||||
this.props.gotoDeviceSettings(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showDeviceMenu() {
|
showDeviceMenu() {
|
||||||
const { device } = this.props;
|
const { device } = this.props;
|
||||||
return device && device.mode === 'normal';
|
return device && device.mode === 'normal';
|
||||||
@ -58,9 +45,14 @@ class MenuItems extends PureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.showDeviceMenu()) return null;
|
if (!this.showDeviceMenu()) return null;
|
||||||
|
const { device } = this.props;
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{/* <Item onClick={() => this.onDeviceMenuClick('settings', this.props.device)}>
|
{/* <Item onClick={() => {
|
||||||
|
this.props.toggleDeviceDropdown(false);
|
||||||
|
this.props.gotoDeviceSettings(device);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon={icons.COG}
|
icon={icons.COG}
|
||||||
size={25}
|
size={25}
|
||||||
@ -68,28 +60,32 @@ class MenuItems extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
<Label>Device settings</Label>
|
<Label>Device settings</Label>
|
||||||
</Item> */}
|
</Item> */}
|
||||||
<Item onClick={() => this.onDeviceMenuClick('forget', this.props.device)}>
|
|
||||||
<Icon
|
|
||||||
icon={icons.EJECT}
|
|
||||||
size={25}
|
|
||||||
color={colors.TEXT_SECONDARY}
|
|
||||||
/>
|
|
||||||
<Label>Forget</Label>
|
|
||||||
</Item>
|
|
||||||
{this.showClone() && (
|
{this.showClone() && (
|
||||||
<Item onClick={() => this.onDeviceMenuClick('clone', this.props.device)}>
|
<Item onClick={() => this.props.duplicateDevice(device)}>
|
||||||
<DeviceIcon device={this.props.device} size={25} color={colors.TEXT_SECONDARY} />
|
<Icon
|
||||||
|
icon={icons.WALLET_STANDARD}
|
||||||
|
size={25}
|
||||||
|
color={colors.TEXT_SECONDARY}
|
||||||
|
/>
|
||||||
<Label>Change wallet type</Label>
|
<Label>Change wallet type</Label>
|
||||||
</Item>
|
</Item>
|
||||||
)}
|
)}
|
||||||
{this.showRenewSession() && (
|
{this.showRenewSession() && (
|
||||||
<Item
|
<Item
|
||||||
onClick={() => this.onDeviceMenuClick('reload')}
|
onClick={() => this.props.acquireDevice()}
|
||||||
>
|
>
|
||||||
<DeviceIcon device={this.props.device} size={25} color={colors.TEXT_SECONDARY} />
|
<DeviceIcon device={this.props.device} size={25} color={colors.TEXT_SECONDARY} />
|
||||||
<Label>Renew session</Label>
|
<Label>Renew session</Label>
|
||||||
</Item>
|
</Item>
|
||||||
)}
|
)}
|
||||||
|
<Item onClick={() => this.props.forgetDevice(device)}>
|
||||||
|
<Icon
|
||||||
|
icon={icons.EJECT}
|
||||||
|
size={25}
|
||||||
|
color={colors.TEXT_SECONDARY}
|
||||||
|
/>
|
||||||
|
<Label>Forget device</Label>
|
||||||
|
</Item>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -100,8 +96,8 @@ MenuItems.propTypes = {
|
|||||||
acquireDevice: PropTypes.func.isRequired,
|
acquireDevice: PropTypes.func.isRequired,
|
||||||
forgetDevice: PropTypes.func.isRequired,
|
forgetDevice: PropTypes.func.isRequired,
|
||||||
duplicateDevice: PropTypes.func.isRequired,
|
duplicateDevice: PropTypes.func.isRequired,
|
||||||
toggleDeviceDropdown: PropTypes.func.isRequired,
|
// toggleDeviceDropdown: PropTypes.func.isRequired,
|
||||||
gotoDeviceSettings: PropTypes.func.isRequired,
|
// gotoDeviceSettings: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MenuItems;
|
export default MenuItems;
|
@ -2,7 +2,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import TrezorConnect from 'trezor-connect';
|
import TrezorConnect from 'trezor-connect';
|
||||||
import type { TrezorDevice } from 'flowtype';
|
|
||||||
|
|
||||||
import COLORS from 'config/colors';
|
import COLORS from 'config/colors';
|
||||||
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
||||||
@ -45,11 +44,6 @@ const StyledDivider = styled(Divider)`
|
|||||||
border: none;
|
border: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type DeviceMenuItem = {
|
|
||||||
type: string;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DeviceMenu extends PureComponent<Props> {
|
class DeviceMenu extends PureComponent<Props> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -74,19 +68,6 @@ class DeviceMenu extends PureComponent<Props> {
|
|||||||
window.removeEventListener('mousedown', this.mouseDownHandler, false);
|
window.removeEventListener('mousedown', this.mouseDownHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeviceMenuClick(item: DeviceMenuItem, device: TrezorDevice): void {
|
|
||||||
if (item.type === 'reload') {
|
|
||||||
this.props.acquireDevice();
|
|
||||||
} else if (item.type === 'forget') {
|
|
||||||
this.props.forgetDevice(device);
|
|
||||||
} else if (item.type === 'clone') {
|
|
||||||
this.props.duplicateDevice(device);
|
|
||||||
} else if (item.type === 'settings') {
|
|
||||||
this.props.toggleDeviceDropdown(false);
|
|
||||||
this.props.gotoDeviceSettings(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getMenuHeight(): number {
|
getMenuHeight(): number {
|
||||||
return this.myRef.current ? this.myRef.current.getBoundingClientRect().height : 0;
|
return this.myRef.current ? this.myRef.current.getBoundingClientRect().height : 0;
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,10 @@ const TextLeft = styled.p`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Divider = ({
|
const Divider = ({
|
||||||
textLeft, textRight, hasBorder = false, className,
|
textLeft, textRight, hasBorder = false, className, testId,
|
||||||
}) => (
|
}) => (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
data-test={testId}
|
||||||
hasBorder={hasBorder}
|
hasBorder={hasBorder}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
@ -39,6 +40,7 @@ Divider.propTypes = {
|
|||||||
textLeft: PropTypes.string,
|
textLeft: PropTypes.string,
|
||||||
textRight: PropTypes.string,
|
textRight: PropTypes.string,
|
||||||
hasBorder: PropTypes.bool,
|
hasBorder: PropTypes.bool,
|
||||||
|
testId: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Divider;
|
export default Divider;
|
||||||
|
@ -12,6 +12,7 @@ import styled from 'styled-components';
|
|||||||
import DeviceHeader from 'components/DeviceHeader';
|
import DeviceHeader from 'components/DeviceHeader';
|
||||||
import * as deviceUtils from 'utils/device';
|
import * as deviceUtils from 'utils/device';
|
||||||
|
|
||||||
|
import Tooltip from 'components/Tooltip';
|
||||||
import AccountMenu from './components/AccountMenu';
|
import AccountMenu from './components/AccountMenu';
|
||||||
import CoinMenu from './components/CoinMenu';
|
import CoinMenu from './components/CoinMenu';
|
||||||
import DeviceMenu from './components/DeviceMenu';
|
import DeviceMenu from './components/DeviceMenu';
|
||||||
@ -24,6 +25,9 @@ const Header = styled(DeviceHeader)`
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const WalletTypeIconWrapper = styled.div`
|
||||||
|
`;
|
||||||
|
|
||||||
const Counter = styled.div`
|
const Counter = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -203,10 +207,24 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
const { selectedDevice, dropdownOpened } = props.wallet;
|
const { selectedDevice, dropdownOpened } = props.wallet;
|
||||||
const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice);
|
const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice);
|
||||||
|
const walletType = selectedDevice && !selectedDevice.useEmptyPassphrase ? 'hidden' : 'standard';
|
||||||
|
const showWalletType = selectedDevice && selectedDevice.features && selectedDevice.features.passphrase_protection;
|
||||||
|
const isDeviceReady = selectedDevice && selectedDevice.connected && selectedDevice.available;
|
||||||
|
|
||||||
|
let walletTooltipMsg = `You are in your ${walletType} wallet.`;
|
||||||
|
if (isDeviceReady) {
|
||||||
|
walletTooltipMsg = walletType === 'standard'
|
||||||
|
? `${walletTooltipMsg} Click here to access your hidden wallet.`
|
||||||
|
: `${walletTooltipMsg} Click here to access your standard or another hidden wallet`;
|
||||||
|
} else {
|
||||||
|
walletTooltipMsg = `${walletTooltipMsg} To access other wallets please connect your device.`;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar isOpen={props.wallet.showSidebar}>
|
<Sidebar isOpen={props.wallet.showSidebar}>
|
||||||
<Header
|
<Header
|
||||||
isSelected
|
isSelected
|
||||||
|
testId="Main__page__device__header"
|
||||||
isHoverable={false}
|
isHoverable={false}
|
||||||
onClickWrapper={() => {
|
onClickWrapper={() => {
|
||||||
if (isDeviceAccessible || this.props.devices.length > 1) {
|
if (isDeviceAccessible || this.props.devices.length > 1) {
|
||||||
@ -218,9 +236,38 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
isOpen={this.props.wallet.dropdownOpened}
|
isOpen={this.props.wallet.dropdownOpened}
|
||||||
icon={(
|
icon={(
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<WalletTypeIcon type={selectedDevice && !selectedDevice.useEmptyPassphrase ? 'hidden' : 'standard'} size={25} color={colors.TEXT_SECONDARY} />
|
{showWalletType ? (
|
||||||
|
<Tooltip
|
||||||
|
content={walletTooltipMsg}
|
||||||
|
maxWidth={200}
|
||||||
|
placement="bottom"
|
||||||
|
enterDelayMs={0.5}
|
||||||
|
>
|
||||||
|
<WalletTypeIconWrapper>
|
||||||
|
<WalletTypeIcon
|
||||||
|
onClick={(e) => {
|
||||||
|
if (selectedDevice && isDeviceReady) {
|
||||||
|
this.props.duplicateDevice(selectedDevice);
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
hoverColor={isDeviceReady ? colors.TEXT_PRIMARY : colors.TEXT_SECONDARY}
|
||||||
|
type={walletType}
|
||||||
|
size={25}
|
||||||
|
color={colors.TEXT_SECONDARY}
|
||||||
|
/>
|
||||||
|
</WalletTypeIconWrapper>
|
||||||
|
</Tooltip>) : null
|
||||||
|
}
|
||||||
{this.props.devices.length > 1 && (
|
{this.props.devices.length > 1 && (
|
||||||
<Counter>{this.props.devices.length}</Counter>
|
<Tooltip
|
||||||
|
content="Number of devices"
|
||||||
|
maxWidth={200}
|
||||||
|
placement="bottom"
|
||||||
|
enterDelayMs={0.5}
|
||||||
|
>
|
||||||
|
<Counter>{this.props.devices.length}</Counter>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Icon
|
<Icon
|
||||||
canAnimate={this.state.clicked === true}
|
canAnimate={this.state.clicked === true}
|
||||||
@ -237,7 +284,7 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
{dropdownOpened && <DeviceMenu ref={this.deviceMenuRef} {...this.props} />}
|
{dropdownOpened && <DeviceMenu ref={this.deviceMenuRef} {...this.props} />}
|
||||||
{isDeviceAccessible && menu}
|
{isDeviceAccessible && menu}
|
||||||
</Body>
|
</Body>
|
||||||
<Footer key="sticky-footer">
|
<Footer data-test="Main__page__footer" key="sticky-footer">
|
||||||
<Help>
|
<Help>
|
||||||
<A
|
<A
|
||||||
href="https://trezor.io/support/"
|
href="https://trezor.io/support/"
|
||||||
|
@ -114,7 +114,11 @@ const StyledBackdrop = styled(Backdrop)`
|
|||||||
|
|
||||||
const Wallet = (props: Props) => (
|
const Wallet = (props: Props) => (
|
||||||
<AppWrapper>
|
<AppWrapper>
|
||||||
<Header sidebarEnabled={!!props.wallet.selectedDevice} sidebarOpened={props.wallet.showSidebar} toggleSidebar={props.toggleSidebar} />
|
<Header
|
||||||
|
sidebarEnabled={!!props.wallet.selectedDevice}
|
||||||
|
sidebarOpened={props.wallet.showSidebar}
|
||||||
|
toggleSidebar={props.toggleSidebar}
|
||||||
|
/>
|
||||||
<AppNotifications />
|
<AppNotifications />
|
||||||
<WalletWrapper>
|
<WalletWrapper>
|
||||||
<StyledBackdrop show={props.wallet.showSidebar} onClick={props.toggleSidebar} animated />
|
<StyledBackdrop show={props.wallet.showSidebar} onClick={props.toggleSidebar} animated />
|
||||||
|
@ -200,7 +200,8 @@ const AdvancedForm = (props: Props) => {
|
|||||||
{ showDefaultGasLimitButton && (
|
{ showDefaultGasLimitButton && (
|
||||||
<Right>
|
<Right>
|
||||||
<StyledLink onClick={setDefaultGasLimit} isGreen>Set default</StyledLink>
|
<StyledLink onClick={setDefaultGasLimit} isGreen>Set default</StyledLink>
|
||||||
</Right>)
|
</Right>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</InputLabelWrapper>
|
</InputLabelWrapper>
|
||||||
)}
|
)}
|
||||||
|
@ -107,7 +107,8 @@ const AccountSummary = (props: Props) => {
|
|||||||
size={24}
|
size={24}
|
||||||
/>
|
/>
|
||||||
</StyledTooltip>
|
</StyledTooltip>
|
||||||
</H2Wrapper>)
|
</H2Wrapper>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -49,7 +49,7 @@ const Image = styled.img`
|
|||||||
const Dashboard = () => (
|
const Dashboard = () => (
|
||||||
<Content>
|
<Content>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Row>
|
<Row data-test="Dashboard__page__content">
|
||||||
<H1>Please select your coin</H1>
|
<H1>Please select your coin</H1>
|
||||||
<StyledP>You will gain access to receiving & sending selected coin</StyledP>
|
<StyledP>You will gain access to receiving & sending selected coin</StyledP>
|
||||||
<Overlay>
|
<Overlay>
|
||||||
|
@ -26,7 +26,7 @@ const StyledParagraph = styled(Paragraph)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Initialize = () => (
|
const Initialize = () => (
|
||||||
<Wrapper>
|
<Wrapper data-test="Page__device__not__initialized">
|
||||||
<Row>
|
<Row>
|
||||||
<H1>Your device is not initialized</H1>
|
<H1>Your device is not initialized</H1>
|
||||||
<StyledParagraph>Please use Bitcoin wallet interface to start initialization process</StyledParagraph>
|
<StyledParagraph>Please use Bitcoin wallet interface to start initialization process</StyledParagraph>
|
||||||
|
26
test/integration/dashboard.spec.js
Normal file
26
test/integration/dashboard.spec.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
describe('Dashboard page', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1366, 1800);
|
||||||
|
cy.visit('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigation', () => {
|
||||||
|
cy.getTestElement('Main__page__navigation')
|
||||||
|
.should('be.visible')
|
||||||
|
.matchImageSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('content', () => {
|
||||||
|
cy.getTestElement('Dashboard__page__content')
|
||||||
|
.should('be.visible')
|
||||||
|
.matchImageSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
|
||||||
|
it('device header', () => {
|
||||||
|
cy.getTestElement('Main__page__device__header')
|
||||||
|
.should('be.visible')
|
||||||
|
.matchImageSnapshot();
|
||||||
|
});
|
||||||
|
});
|
7
test/plugins/index.js
Normal file
7
test/plugins/index.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
const {
|
||||||
|
addMatchImageSnapshotPlugin,
|
||||||
|
} = require('cypress-image-snapshot/plugin');
|
||||||
|
|
||||||
|
module.exports = (on) => {
|
||||||
|
addMatchImageSnapshotPlugin(on);
|
||||||
|
};
|
6
test/scripts/init-device.js
Normal file
6
test/scripts/init-device.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import '@babel/polyfill';
|
||||||
|
import { initSeedAllDevice } from 'trezor-bridge-communicator';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await initSeedAllDevice();
|
||||||
|
})();
|
20
test/scripts/run-all.sh
Executable file
20
test/scripts/run-all.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# run bridge
|
||||||
|
cd /trezor-bridge && ./extracted/usr/bin/trezord -ed 21324:21325 -u=false &
|
||||||
|
|
||||||
|
# run emulator
|
||||||
|
cd /trezor-emulator/trezor-core && PYOPT=0 ./emu.sh &
|
||||||
|
|
||||||
|
# run wallet
|
||||||
|
cd /trezor-wallet && yarn run server:stable &
|
||||||
|
|
||||||
|
# init device
|
||||||
|
npx babel-node /trezor-wallet/test/scripts/init-device.js &
|
||||||
|
|
||||||
|
# run tests
|
||||||
|
yarn run test-integration:gitlab -c baseUrl="https://localhost:8080/#/"
|
BIN
test/snapshots/All Specs/Dashboard page -- content.snap.png
Normal file
BIN
test/snapshots/All Specs/Dashboard page -- content.snap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
test/snapshots/All Specs/Dashboard page -- navigation.snap.png
Normal file
BIN
test/snapshots/All Specs/Dashboard page -- navigation.snap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
5
test/support/commands.js
Normal file
5
test/support/commands.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command';
|
||||||
|
|
||||||
|
addMatchImageSnapshotCommand();
|
||||||
|
|
||||||
|
Cypress.Commands.add('getTestElement', selector => cy.get(`[data-test="${selector}"]`));
|
5
test/support/index.js
Normal file
5
test/support/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import './commands';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
window.localStorage.setItem('/betaModalPrivacy', true);
|
||||||
|
});
|
@ -2,7 +2,6 @@ import webpack from 'webpack';
|
|||||||
import GitRevisionPlugin from 'git-revision-webpack-plugin';
|
import GitRevisionPlugin from 'git-revision-webpack-plugin';
|
||||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||||
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin';
|
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin';
|
||||||
import FlowWebpackPlugin from 'flow-webpack-plugin';
|
|
||||||
import WebpackBuildNotifierPlugin from 'webpack-build-notifier';
|
import WebpackBuildNotifierPlugin from 'webpack-build-notifier';
|
||||||
|
|
||||||
// turn on for bundle analyzing
|
// turn on for bundle analyzing
|
||||||
@ -45,6 +44,7 @@ module.exports = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: [
|
use: [
|
||||||
'babel-loader',
|
'babel-loader',
|
||||||
|
'react-hot-loader/webpack',
|
||||||
{
|
{
|
||||||
loader: 'eslint-loader',
|
loader: 'eslint-loader',
|
||||||
options: {
|
options: {
|
||||||
@ -63,7 +63,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.(png|gif|jpg)$/,
|
test: /\.(png|gif|jpg)$/,
|
||||||
loader: 'file-loader?name=./images/[name].[ext]',
|
loader: 'file-loader?name=./images/[name].[ext]',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './images',
|
outputPath: './images',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -71,7 +71,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './fonts',
|
outputPath: './fonts',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -81,7 +81,7 @@ module.exports = {
|
|||||||
test: /\.json/,
|
test: /\.json/,
|
||||||
exclude: [/(node_modules)/, TRANSLATIONS],
|
exclude: [/(node_modules)/, TRANSLATIONS],
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './data',
|
outputPath: './data',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -105,9 +105,6 @@ module.exports = {
|
|||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
COMMITHASH: JSON.stringify(gitRevisionPlugin.commithash()),
|
COMMITHASH: JSON.stringify(gitRevisionPlugin.commithash()),
|
||||||
}),
|
}),
|
||||||
new FlowWebpackPlugin({
|
|
||||||
reportingSeverity: 'warning',
|
|
||||||
}),
|
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
chunks: ['index'],
|
chunks: ['index'],
|
||||||
template: `${SRC}index.html`,
|
template: `${SRC}index.html`,
|
||||||
|
@ -67,7 +67,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.(png|gif|jpg)$/,
|
test: /\.(png|gif|jpg)$/,
|
||||||
loader: 'file-loader?name=./images/[name].[ext]',
|
loader: 'file-loader?name=./images/[name].[ext]',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './images',
|
outputPath: './images',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -75,7 +75,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './fonts',
|
outputPath: './fonts',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -85,7 +85,7 @@ module.exports = {
|
|||||||
test: /\.json/,
|
test: /\.json/,
|
||||||
exclude: /(node_modules)/,
|
exclude: /(node_modules)/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './data',
|
outputPath: './data',
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
},
|
},
|
||||||
@ -94,7 +94,7 @@ module.exports = {
|
|||||||
type: 'javascript/auto',
|
type: 'javascript/auto',
|
||||||
test: /\.wasm$/,
|
test: /\.wasm$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
name: 'js/[name].[ext]',
|
name: 'js/[name].[ext]',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import GitRevisionPlugin from 'git-revision-webpack-plugin';
|
import GitRevisionPlugin from 'git-revision-webpack-plugin';
|
||||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||||
@ -6,7 +5,6 @@ import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin';
|
|||||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||||
import { SRC, BUILD, PUBLIC } from './constants';
|
import { SRC, BUILD, PUBLIC } from './constants';
|
||||||
|
|
||||||
|
|
||||||
const gitRevisionPlugin = new GitRevisionPlugin();
|
const gitRevisionPlugin = new GitRevisionPlugin();
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -30,7 +28,7 @@ module.exports = {
|
|||||||
test: /\.(png|gif|jpg)$/,
|
test: /\.(png|gif|jpg)$/,
|
||||||
exclude: /(node_modules)/,
|
exclude: /(node_modules)/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './images',
|
outputPath: './images',
|
||||||
name: '[name].[hash].[ext]',
|
name: '[name].[hash].[ext]',
|
||||||
},
|
},
|
||||||
@ -38,7 +36,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
test: /\.(ttf|eot|svg|woff|woff2)$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './fonts',
|
outputPath: './fonts',
|
||||||
name: '[name].[hash].[ext]',
|
name: '[name].[hash].[ext]',
|
||||||
},
|
},
|
||||||
@ -48,7 +46,7 @@ module.exports = {
|
|||||||
test: /\.json/,
|
test: /\.json/,
|
||||||
exclude: /(node_modules)/,
|
exclude: /(node_modules)/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
options: {
|
||||||
outputPath: './data',
|
outputPath: './data',
|
||||||
name: '[name].[hash].[ext]',
|
name: '[name].[hash].[ext]',
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user