* Fix swapOwners threshold displayed as hex in tx list * Refactor spinner in empty table * Fix number of rows per page in table pagination * Add use of EtherscanLink component * Set short version of strings in tx list * Adjust styles in tx list * Add more styles to table * WIP * An attempt to fix #204 by showing UNKNOWN instead of failed to fetch token symbol * Table pagination style fixes * Show confirm transaction button in owner list * Update dependencies * Add confirmation icons to owner list in tx list * exclude unneeded stuff from travis.yml * Adds cookie permissions to localStorage/redux state * Update dependencies * Adds action * Adds files to git * (fix) linting issues * (update) flow-typed * (update) .eslint and .flowconfig * (add) cookie banner * Finish cookie banner implementation * (Add) checkbox's disabled style. * Removes redux for cookiesStorage * Fix cookieStore deletion * Increase TO_EXP for bignumber.js * Fixs cookies acceptance * Fixs cookies banner verbiage Fix "x" in wrong place for snackbar messages * (fix) added correct polished library and import, updated flow-typed * (update) removed polish flow type, added js-cookie flow type * Add link to cookie policy, use generic links for legal docs * Remove link to cookie policy from sidebar, link cookie policy in the banner * Mock Safe creation transaction * Format code * Fix break statement * Remove deployment of storybook * Let the user re-open the cookie banner * Update tx status messages and visual confirmation progress * Fix svg in tx confirmation progress * Add styles to tx type in tx list * Replace nonce in tx list with tx id * Update opacity of cancelled tx * Fix short version of address * remove withMutations from cookies reducer, move utils/cookies to logic/cookies * Now the sidebar closes when the cookie banner is toggled * Fix styles in tx list * Add Pending status in tx description * (remove) unused library * Adds cookies utils Replaces localStorage with cookies Adds js-cookie * Set 25 rows per page in tx list by default * Align tx table * Adjust tx table and tx details borders * Fix fetching transactions to show Safe creation tx alone * Fix failed Safe creation transaction * Add styles to tx data * Refactor and fix owner list in transaction * Refactor use of theme variables * Remove storybook files * Update dependencies * Fix warnings * Fix dependencies * Update file-loader config * Fix owner colors in the tx confirmation progress * Fix transaction type icon height * Tx list adjustments * Update readme
1
.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
build_webpack/
|
build_webpack/
|
||||||
build_storybook/
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
build/
|
build/
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import '@storybook/addon-actions/register'
|
|
||||||
import '@storybook/addon-links/register'
|
|
||||||
import '@storybook/addon-knobs/register'
|
|
@ -1,35 +0,0 @@
|
|||||||
import 'babel-polyfill'
|
|
||||||
import { addDecorator, configure } from '@storybook/react'
|
|
||||||
import { withKnobs } from '@storybook/addon-knobs'
|
|
||||||
import { MuiThemeProvider } from '@material-ui/core/styles'
|
|
||||||
import * as React from 'react'
|
|
||||||
import { Provider } from 'react-redux'
|
|
||||||
import StoryRouter from 'storybook-router'
|
|
||||||
import { store } from '~/store'
|
|
||||||
import theme from '~/theme/mui'
|
|
||||||
import 'index.scss'
|
|
||||||
|
|
||||||
(function (global) {
|
|
||||||
//Useful for adding data and libraries to window object.
|
|
||||||
})(typeof window !== 'undefined' ? window : {});
|
|
||||||
|
|
||||||
addDecorator(withKnobs);
|
|
||||||
addDecorator(StoryRouter())
|
|
||||||
|
|
||||||
addDecorator((story) => (
|
|
||||||
<Provider store={store}>
|
|
||||||
<MuiThemeProvider theme={theme}>
|
|
||||||
{ story() }
|
|
||||||
</MuiThemeProvider>
|
|
||||||
</Provider>
|
|
||||||
))
|
|
||||||
|
|
||||||
const components = require.context('../src/components', true, /\.stories\.((js|ts)x?)$/)
|
|
||||||
const routes = require.context('../src/routes', true, /\.stories\.((js|ts)x?)$/)
|
|
||||||
|
|
||||||
function loadStories() {
|
|
||||||
components.keys().forEach((filename) => components(filename))
|
|
||||||
routes.keys().forEach((filename) => routes(filename))
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(loadStories, module)
|
|
@ -1 +0,0 @@
|
|||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
|
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
process.env.NODE_ENV = 'development'
|
|
||||||
const prodConfig = require('../config/webpack.config.dev');
|
|
||||||
|
|
||||||
module.exports = function(storybookConfig, configType) {
|
|
||||||
|
|
||||||
const config = Object.assign({}, prodConfig);
|
|
||||||
|
|
||||||
storybookConfig.module.rules = storybookConfig.module.rules.concat(config.module.rules)
|
|
||||||
storybookConfig.resolve = config.resolve;
|
|
||||||
|
|
||||||
return storybookConfig;
|
|
||||||
};
|
|
@ -133,6 +133,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
|
esModule: false,
|
||||||
name: 'img/[hash].[ext]',
|
name: 'img/[hash].[ext]',
|
||||||
esModule: false
|
esModule: false
|
||||||
},
|
},
|
||||||
|
122
flow-typed/npm/@sambego/storybook-state_vx.x.x.js
vendored
@ -1,122 +0,0 @@
|
|||||||
// flow-typed signature: 9e597e3161a1342a9e77ec9437783354
|
|
||||||
// flow-typed version: <<STUB>>/@sambego/storybook-state_v^1.3.6/flow_v0.112.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* '@sambego/storybook-state'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module '@sambego/storybook-state/dist' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/dist/State' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/dist/StateDecorator' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/dist/Store' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/enzyme.config' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/jest.config' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/src' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/src/State' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/src/StateDecorator' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/src/Store' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/tests/State.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/tests/StateDecorator.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@sambego/storybook-state/tests/Store.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module '@sambego/storybook-state/dist/index' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/dist/index.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/dist/State.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/dist/State'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/dist/StateDecorator.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/dist/StateDecorator'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/dist/Store.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/dist/Store'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/enzyme.config.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/enzyme.config'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/jest.config.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/jest.config'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/src/index' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/src'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/src/index.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/src'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/src/State.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/src/State'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/src/StateDecorator.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/src/StateDecorator'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/src/Store.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/src/Store'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/tests/State.test.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/tests/State.test'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/tests/StateDecorator.test.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/tests/StateDecorator.test'>;
|
|
||||||
}
|
|
||||||
declare module '@sambego/storybook-state/tests/Store.test.js' {
|
|
||||||
declare module.exports: $Exports<'@sambego/storybook-state/tests/Store.test'>;
|
|
||||||
}
|
|
187
flow-typed/npm/@storybook/addon-actions_vx.x.x.js
vendored
@ -1,187 +0,0 @@
|
|||||||
// flow-typed signature: 64c369e4ed0c4a705b2f36b522874cac
|
|
||||||
// flow-typed version: <<STUB>>/@storybook/addon-actions_v5.2.6/flow_v0.112.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* '@storybook/addon-actions'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module '@storybook/addon-actions/dist/components/ActionLogger' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/components/ActionLogger/style' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/constants' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/containers/ActionLogger' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/manager' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionDisplay' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionOptions' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionsFunction' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionsMap' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/DecoratorFunction' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models/HandlerFunction' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/models' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/action' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/actions' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/configureActions' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/decorateAction' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/withActions' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/dist/typings.d' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-actions/register' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module '@storybook/addon-actions/dist/components/ActionLogger/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/components/ActionLogger'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/components/ActionLogger/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/components/ActionLogger'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/components/ActionLogger/style.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/components/ActionLogger/style'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/constants.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/constants'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/containers/ActionLogger/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/containers/ActionLogger'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/containers/ActionLogger/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/containers/ActionLogger'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/manager.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/manager'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionDisplay.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/ActionDisplay'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionOptions.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/ActionOptions'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionsFunction.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/ActionsFunction'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/ActionsMap.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/ActionsMap'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/DecoratorFunction.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/DecoratorFunction'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/HandlerFunction.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models/HandlerFunction'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/models/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/models'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/action.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview/action'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/actions.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview/actions'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/configureActions.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview/configureActions'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/decorateAction.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview/decorateAction'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/preview/withActions.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/preview/withActions'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/dist/typings.d.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/dist/typings.d'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-actions/register.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-actions/register'>;
|
|
||||||
}
|
|
283
flow-typed/npm/@storybook/addon-knobs_vx.x.x.js
vendored
@ -1,283 +0,0 @@
|
|||||||
// flow-typed signature: 90624ef390fe4c5befd27eedd08d7ad2
|
|
||||||
// flow-typed version: <<STUB>>/@storybook/addon-knobs_v5.2.6/flow_v0.112.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* '@storybook/addon-knobs'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module '@storybook/addon-knobs/angular' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/__types__/knob-test-cases' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/Panel' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/PropForm' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Array' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Boolean' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Button' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Checkboxes' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Color' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Date' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Files' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Number' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Object' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Options' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Radio' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Select' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Text' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/types' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/converters' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/deprecated' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/KnobManager' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/KnobStore' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/register' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/registerKnobs' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/shared' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/type-defs' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/dist/typings.d' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/html' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/marko' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/mithril' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/polymer' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/react' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/register' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-knobs/vue' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module '@storybook/addon-knobs/angular.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/angular'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/__types__/knob-test-cases.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/__types__/knob-test-cases'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/Panel.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/Panel'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/PropForm.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/PropForm'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Array.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Array'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Boolean.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Boolean'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Button.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Button'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Checkboxes.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Checkboxes'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Color.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Color'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Date.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Date'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Files.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Files'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Number.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Number'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Object.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Object'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Options.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Options'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Radio.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Radio'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Select.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Select'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/Text.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/Text'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/components/types/types.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/components/types/types'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/converters.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/converters'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/deprecated.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/deprecated'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/KnobManager.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/KnobManager'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/KnobStore.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/KnobStore'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/register.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/register'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/registerKnobs.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/registerKnobs'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/shared.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/shared'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/type-defs.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/type-defs'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/dist/typings.d.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/dist/typings.d'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/html.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/html'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/marko.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/marko'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/mithril.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/mithril'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/polymer.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/polymer'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/react.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/react'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/register.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/register'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-knobs/vue.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-knobs/vue'>;
|
|
||||||
}
|
|
101
flow-typed/npm/@storybook/addon-links_vx.x.x.js
vendored
@ -1,101 +0,0 @@
|
|||||||
// flow-typed signature: f6f4916ab4d700d3db6ac07b4264aa7e
|
|
||||||
// flow-typed version: <<STUB>>/@storybook/addon-links_v5.2.6/flow_v0.112.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* '@storybook/addon-links'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module '@storybook/addon-links/dist/constants' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/manager' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/preview' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/react/components/link' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/react/components/RoutedLink' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/react' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/dist/typings.d' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/react' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@storybook/addon-links/register' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module '@storybook/addon-links/dist/constants.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/constants'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/manager.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/manager'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/preview.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/preview'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/react/components/link.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/react/components/link'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/react/components/RoutedLink.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/react/components/RoutedLink'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/react/index' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/react'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/react/index.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/react'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/dist/typings.d.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/dist/typings.d'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/react.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/react'>;
|
|
||||||
}
|
|
||||||
declare module '@storybook/addon-links/register.js' {
|
|
||||||
declare module.exports: $Exports<'@storybook/addon-links/register'>;
|
|
||||||
}
|
|
61
flow-typed/npm/@storybook/react_v5.x.x.js
vendored
@ -1,61 +0,0 @@
|
|||||||
// flow-typed signature: e484579841f3cb1e8f57a768abc4642d
|
|
||||||
// flow-typed version: c6154227d1/@storybook/react_v5.x.x/flow_>=v0.104.x
|
|
||||||
|
|
||||||
type NodeModule = typeof module;
|
|
||||||
|
|
||||||
declare module '@storybook/react' {
|
|
||||||
declare type Context = {
|
|
||||||
kind: string,
|
|
||||||
story: string,
|
|
||||||
...
|
|
||||||
};
|
|
||||||
declare type Renderable =
|
|
||||||
| string
|
|
||||||
| number
|
|
||||||
| React$Element<any>
|
|
||||||
| Iterable<?Renderable>;
|
|
||||||
declare type RenderCallback = (
|
|
||||||
context: Context
|
|
||||||
) => Renderable;
|
|
||||||
declare type RenderFunction = () => Renderable;
|
|
||||||
|
|
||||||
declare type StoryDecorator = (
|
|
||||||
story: RenderFunction,
|
|
||||||
context: Context
|
|
||||||
) => Renderable;
|
|
||||||
|
|
||||||
declare type DecoratorParameters = { [key: string]: any, ... };
|
|
||||||
|
|
||||||
declare interface Story {
|
|
||||||
+kind: string;
|
|
||||||
add(
|
|
||||||
storyName: string,
|
|
||||||
callback: RenderCallback,
|
|
||||||
parameters?: DecoratorParameters
|
|
||||||
): Story;
|
|
||||||
addDecorator(decorator: StoryDecorator): Story;
|
|
||||||
addParameters(parameters: DecoratorParameters): Story;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare interface StoryObject {
|
|
||||||
name: string;
|
|
||||||
render: RenderFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare interface StoryBucket {
|
|
||||||
kind: string;
|
|
||||||
filename: string;
|
|
||||||
stories: Array<StoryObject>;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare function addDecorator(decorator: StoryDecorator): void;
|
|
||||||
declare function addParameters(parameters: DecoratorParameters): void;
|
|
||||||
declare function clearDecorators(): void;
|
|
||||||
declare function configure(fn: () => void, module: NodeModule): void;
|
|
||||||
declare function setAddon(addon: Object): void;
|
|
||||||
declare function storiesOf(name: string, module: NodeModule): Story;
|
|
||||||
declare function storiesOf<T>(name: string, module: NodeModule): Story & T;
|
|
||||||
declare function forceReRender(): void;
|
|
||||||
|
|
||||||
declare function getStorybook(): Array<StoryBucket>;
|
|
||||||
}
|
|
249
flow-typed/npm/storybook-host_vx.x.x.js
vendored
@ -1,249 +0,0 @@
|
|||||||
// flow-typed signature: 48ec61af419d1ece506839678031f356
|
|
||||||
// flow-typed version: <<STUB>>/storybook-host_v5.1.0/flow_v0.112.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an autogenerated libdef stub for:
|
|
||||||
*
|
|
||||||
* 'storybook-host'
|
|
||||||
*
|
|
||||||
* Fill this stub out by replacing all the `any` types.
|
|
||||||
*
|
|
||||||
* Once filled out, we encourage you to share your work with the
|
|
||||||
* community by sending a pull request to:
|
|
||||||
* https://github.com/flowtype/flow-typed
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare module 'storybook-host' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We include stubs for each file inside this npm package in case you need to
|
|
||||||
* require those files directly. Feel free to delete any files that aren't
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
declare module 'storybook-host/lib/common/alignment' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/color' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/css' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/glamor' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-flex.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-image.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-positioning.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-spacing.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/css/types' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/libs' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/common/util' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/AlignmentContainer' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/ComponentHost.stories' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/ComponentHost' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/ComponentHost.stories' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/CropMark' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/CropMarks' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/decorators/host' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/index.test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/test/Foo' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/test' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'storybook-host/lib/types' {
|
|
||||||
declare module.exports: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filename aliases
|
|
||||||
declare module 'storybook-host/lib/common/alignment.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/alignment'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/color.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/color'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/css.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/css'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/glamor.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/glamor'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-flex.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/test/css-flex.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-image.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/test/css-image.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-positioning.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/test/css-positioning.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css-spacing.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/test/css-spacing.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/test/css.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/test/css.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/css/types.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/css/types'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/libs.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/libs'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/common/util.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/common/util'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/AlignmentContainer.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/AlignmentContainer/AlignmentContainer'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/ComponentHost.stories.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/AlignmentContainer/ComponentHost.stories'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/AlignmentContainer'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/AlignmentContainer/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/AlignmentContainer'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/ComponentHost.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/ComponentHost/ComponentHost'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/ComponentHost.stories.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/ComponentHost/ComponentHost.stories'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/ComponentHost'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/ComponentHost/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/ComponentHost'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/CropMark.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/CropMarks/CropMark'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/CropMarks.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/CropMarks/CropMarks'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/CropMarks'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/components/CropMarks/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/components/CropMarks'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/decorators/host.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/decorators/host'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/index.test.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/index.test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/test/Foo.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/test/Foo'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/test/index' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/test/index.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/test'>;
|
|
||||||
}
|
|
||||||
declare module 'storybook-host/lib/types.js' {
|
|
||||||
declare module.exports: $Exports<'storybook-host/lib/types'>;
|
|
||||||
}
|
|
45
flow-typed/npm/storybook-router_v0.x.x.js
vendored
@ -1,45 +0,0 @@
|
|||||||
// flow-typed signature: c2d42e89f2eeb1cdff2d4d7dea9fd97b
|
|
||||||
// flow-typed version: c6154227d1/storybook-router_v0.x.x/flow_>=v0.104.x
|
|
||||||
|
|
||||||
type LocationShape = {
|
|
||||||
pathname?: string,
|
|
||||||
search?: string,
|
|
||||||
hash?: string,
|
|
||||||
state?: any,
|
|
||||||
...
|
|
||||||
};
|
|
||||||
|
|
||||||
type GetUserConfirmation = (
|
|
||||||
message: string,
|
|
||||||
callback: (confirmed: boolean) => void
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
declare module "storybook-router" {
|
|
||||||
declare type Context = {
|
|
||||||
kind: string,
|
|
||||||
story: string,
|
|
||||||
...
|
|
||||||
};
|
|
||||||
declare type Renderable = React$Element<*>;
|
|
||||||
declare type RenderFunction = () => Renderable | Array<Renderable>;
|
|
||||||
|
|
||||||
declare type StoryDecorator = (
|
|
||||||
story: RenderFunction,
|
|
||||||
context: Context
|
|
||||||
) => Renderable | null;
|
|
||||||
|
|
||||||
declare type Links = { [key: string]: (kind: string, story: string) => Function, ... };
|
|
||||||
|
|
||||||
declare type RouterProps = {
|
|
||||||
initialEntry?: Array<string>,
|
|
||||||
autoRoute?: boolean,
|
|
||||||
initialEntries?: Array<LocationShape | string>,
|
|
||||||
initialIndex?: number,
|
|
||||||
getUserConfirmation?: GetUserConfirmation,
|
|
||||||
keyLength?: number,
|
|
||||||
children?: React$Element<*>,
|
|
||||||
...
|
|
||||||
};
|
|
||||||
|
|
||||||
declare module.exports: { (links?: Links, routerProps?: RouterProps): StoryDecorator, ... };
|
|
||||||
}
|
|
18
package.json
@ -18,12 +18,10 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node scripts/build.js",
|
"build": "node scripts/build.js",
|
||||||
"build-mainnet": "REACT_APP_NETWORK=mainnet yarn build",
|
"build-mainnet": "REACT_APP_NETWORK=mainnet yarn build",
|
||||||
"build-storybook": "build-storybook -o build_storybook",
|
|
||||||
"flow": "flow",
|
"flow": "flow",
|
||||||
"precommit": "./precommit.sh",
|
"precommit": "./precommit.sh",
|
||||||
"start": "node scripts/start.js",
|
"start": "node scripts/start.js",
|
||||||
"start-mainnet": "REACT_APP_NETWORK=mainnet yarn start",
|
"start-mainnet": "REACT_APP_NETWORK=mainnet yarn start",
|
||||||
"storybook": "start-storybook -p 6006",
|
|
||||||
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
||||||
"format": "prettier-eslint \"src/**/*.js\" --write"
|
"format": "prettier-eslint \"src/**/*.js\" --write"
|
||||||
},
|
},
|
||||||
@ -44,6 +42,7 @@
|
|||||||
"bignumber.js": "9.0.0",
|
"bignumber.js": "9.0.0",
|
||||||
"connected-react-router": "6.6.1",
|
"connected-react-router": "6.6.1",
|
||||||
"date-fns": "2.8.1",
|
"date-fns": "2.8.1",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
"ethereum-ens": "0.7.8",
|
"ethereum-ens": "0.7.8",
|
||||||
"final-form": "4.18.6",
|
"final-form": "4.18.6",
|
||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
@ -56,6 +55,7 @@
|
|||||||
"polished": "^3.4.2",
|
"polished": "^3.4.2",
|
||||||
"qrcode.react": "1.0.0",
|
"qrcode.react": "1.0.0",
|
||||||
"react": "16.12.0",
|
"react": "16.12.0",
|
||||||
|
"react-dev-utils": "^10.0.0",
|
||||||
"react-dom": "16.12.0",
|
"react-dom": "16.12.0",
|
||||||
"react-final-form": "6.3.3",
|
"react-final-form": "6.3.3",
|
||||||
"react-final-form-listeners": "^1.0.2",
|
"react-final-form-listeners": "^1.0.2",
|
||||||
@ -70,10 +70,9 @@
|
|||||||
"redux-actions": "^2.6.5",
|
"redux-actions": "^2.6.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.0.0",
|
||||||
"squarelink": "^1.1.3",
|
"squarelink": "^1.1.4",
|
||||||
"web3": "1.2.4",
|
"web3": "1.2.4",
|
||||||
"web3connect": "^1.0.0-beta.23",
|
"web3connect": "^1.0.0-beta.23"
|
||||||
"react-ga": "^2.7.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.7.5",
|
"@babel/cli": "7.7.5",
|
||||||
@ -100,11 +99,6 @@
|
|||||||
"@babel/preset-env": "7.7.6",
|
"@babel/preset-env": "7.7.6",
|
||||||
"@babel/preset-flow": "7.7.4",
|
"@babel/preset-flow": "7.7.4",
|
||||||
"@babel/preset-react": "7.7.4",
|
"@babel/preset-react": "7.7.4",
|
||||||
"@sambego/storybook-state": "^1.3.6",
|
|
||||||
"@storybook/addon-actions": "5.2.8",
|
|
||||||
"@storybook/addon-knobs": "5.2.8",
|
|
||||||
"@storybook/addon-links": "5.2.8",
|
|
||||||
"@storybook/react": "5.2.8",
|
|
||||||
"@testing-library/react": "9.3.2",
|
"@testing-library/react": "9.3.2",
|
||||||
"autoprefixer": "9.7.3",
|
"autoprefixer": "9.7.3",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
@ -118,7 +112,7 @@
|
|||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"css-loader": "3.2.1",
|
"css-loader": "3.2.1",
|
||||||
"detect-port": "^1.3.0",
|
"detect-port": "^1.3.0",
|
||||||
"eslint": "5.16.0",
|
"eslint": "6.7.2",
|
||||||
"eslint-config-airbnb": "18.0.1",
|
"eslint-config-airbnb": "18.0.1",
|
||||||
"eslint-plugin-flowtype": "4.5.2",
|
"eslint-plugin-flowtype": "4.5.2",
|
||||||
"eslint-plugin-import": "2.19.1",
|
"eslint-plugin-import": "2.19.1",
|
||||||
@ -142,8 +136,6 @@
|
|||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier-eslint-cli": "5.0.0",
|
"prettier-eslint-cli": "5.0.0",
|
||||||
"run-with-testrpc": "0.3.1",
|
"run-with-testrpc": "0.3.1",
|
||||||
"storybook-host": "5.1.0",
|
|
||||||
"storybook-router": "^0.3.4",
|
|
||||||
"style-loader": "1.0.1",
|
"style-loader": "1.0.1",
|
||||||
"terser-webpack-plugin": "^2.2.2",
|
"terser-webpack-plugin": "^2.2.2",
|
||||||
"truffle": "5.1.3",
|
"truffle": "5.1.3",
|
||||||
|
@ -57,6 +57,8 @@ git clone https://github.com/gnosis/safe-transaction-service.git
|
|||||||
cd safe-transaction-history
|
cd safe-transaction-history
|
||||||
git checkout develop
|
git checkout develop
|
||||||
docker-compose build
|
docker-compose build
|
||||||
|
# it comes enabled by default in docker-compose
|
||||||
|
sudo service postgresql stop
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
Check that the service is running at https://localhost:8000
|
Check that the service is running at https://localhost:8000
|
||||||
|
@ -8,7 +8,7 @@ import { makeStyles } from '@material-ui/core/styles'
|
|||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import Link from '~/components/layout/Link'
|
import Link from '~/components/layout/Link'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import { primary, mainFontFamily } from '~/theme/variables'
|
import { primary, mainFontFamily, md } from '~/theme/variables'
|
||||||
import type { CookiesProps } from '~/logic/cookies/model/cookie'
|
import type { CookiesProps } from '~/logic/cookies/model/cookie'
|
||||||
import { COOKIES_KEY } from '~/logic/cookies/model/cookie'
|
import { COOKIES_KEY } from '~/logic/cookies/model/cookie'
|
||||||
import { loadFromCookie, saveCookie } from '~/logic/cookies/utils'
|
import { loadFromCookie, saveCookie } from '~/logic/cookies/utils'
|
||||||
@ -38,7 +38,7 @@ const useStyles = makeStyles({
|
|||||||
text: {
|
text: {
|
||||||
color: primary,
|
color: primary,
|
||||||
fontFamily: mainFontFamily,
|
fontFamily: mainFontFamily,
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
lineHeight: '1.38',
|
lineHeight: '1.38',
|
||||||
margin: '0 0 25px',
|
margin: '0 0 25px',
|
||||||
|
@ -13,14 +13,14 @@ const useStyles = makeStyles({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
padding: xs,
|
margin: `0 ${xs}`,
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
transition: 'background-color .2s ease-in-out',
|
transition: 'background-color .2s ease-in-out',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: '#F0EFEE',
|
backgroundColor: '#F0EFEE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inreasedPopperZindex: {
|
increasedPopperZindex: {
|
||||||
zIndex: 2001,
|
zIndex: 2001,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -33,7 +33,7 @@ type CopyBtnProps = {
|
|||||||
const CopyBtn = ({ content, increaseZindex = false }: CopyBtnProps) => {
|
const CopyBtn = ({ content, increaseZindex = false }: CopyBtnProps) => {
|
||||||
const [clicked, setClicked] = useState<boolean>(false)
|
const [clicked, setClicked] = useState<boolean>(false)
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
const customClasses = increaseZindex ? { popper: classes.increasedPopperZindex } : {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
@ -12,14 +12,14 @@ const useStyles = makeStyles({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: xs,
|
margin: `0 ${xs}`,
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
transition: 'background-color .2s ease-in-out',
|
transition: 'background-color .2s ease-in-out',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: '#F0EFEE',
|
backgroundColor: '#F0EFEE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inreasedPopperZindex: {
|
increasedPopperZindex: {
|
||||||
zIndex: 2001,
|
zIndex: 2001,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -32,7 +32,7 @@ type EtherscanBtnProps = {
|
|||||||
|
|
||||||
const EtherscanBtn = ({ type, value, increaseZindex = false }: EtherscanBtnProps) => {
|
const EtherscanBtn = ({ type, value, increaseZindex = false }: EtherscanBtnProps) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
const customClasses = increaseZindex ? { popper: classes.increasedPopperZindex } : {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip title="Show details on Etherscan" placement="top" classes={customClasses}>
|
<Tooltip title="Show details on Etherscan" placement="top" classes={customClasses}>
|
||||||
|
@ -1,25 +1,30 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
import Block from '~/components/layout/Block'
|
||||||
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
|
import CopyBtn from '~/components/CopyBtn'
|
||||||
|
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||||
import { secondary } from '~/theme/variables'
|
import { styles } from './style.js'
|
||||||
|
|
||||||
const openIconStyle = {
|
|
||||||
height: '13px',
|
|
||||||
color: secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
type EtherscanLinkProps = {
|
type EtherscanLinkProps = {
|
||||||
type: 'tx' | 'address',
|
type: 'tx' | 'address',
|
||||||
value: string,
|
value: string,
|
||||||
|
cut?: number,
|
||||||
|
classes: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
const EtherscanLink = ({ type, value }: EtherscanLinkProps) => (
|
const EtherscanLink = ({
|
||||||
<a href={getEtherScanLink(type, value)} target="_blank" rel="noopener noreferrer">
|
type, value, cut, classes,
|
||||||
{shortVersionOf(value, 4)}
|
}: EtherscanLinkProps) => (
|
||||||
<OpenInNew style={openIconStyle} />
|
<Block className={classes.etherscanLink}>
|
||||||
</a>
|
<Paragraph size="md" noMargin>
|
||||||
|
{cut ? shortVersionOf(value, cut) : value}
|
||||||
|
</Paragraph>
|
||||||
|
<CopyBtn content={value} />
|
||||||
|
<EtherscanBtn type={type} value={value} />
|
||||||
|
</Block>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default EtherscanLink
|
export default withStyles(styles)(EtherscanLink)
|
||||||
|
8
src/components/EtherscanLink/style.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export const styles = () => ({
|
||||||
|
etherscanLink: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
})
|
@ -33,7 +33,7 @@ const styles = () => ({
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
|
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
|
||||||
minWidth: '280px',
|
minWidth: '280px',
|
||||||
borderRadius: '8px',
|
borderRadius: sm,
|
||||||
marginTop: '11px',
|
marginTop: '11px',
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import Layout from './Layout'
|
|
||||||
import ProviderAccesible from './ProviderInfo/ProviderAccesible'
|
|
||||||
import UserDetails from './ProviderDetails/UserDetails'
|
|
||||||
import ProviderDisconnected from './ProviderInfo/ProviderDisconnected'
|
|
||||||
import ConnectDetails from './ProviderDetails/ConnectDetails'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Components /Header', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('Connected', () => {
|
|
||||||
const provider = 'Metamask'
|
|
||||||
const userAddress = '0x873faa4cddd5b157e8e5a57e7a5479afc5d30moe'
|
|
||||||
const network = 'RINKEBY'
|
|
||||||
const info = <ProviderAccesible provider={provider} network={network} userAddress={userAddress} connected />
|
|
||||||
const details = <UserDetails provider={provider} network={network} userAddress={userAddress} connected />
|
|
||||||
|
|
||||||
return <Layout providerInfo={info} providerDetails={details} />
|
|
||||||
})
|
|
||||||
.add('Disconnected', () => {
|
|
||||||
const info = <ProviderDisconnected />
|
|
||||||
const details = <ConnectDetails />
|
|
||||||
|
|
||||||
return <Layout providerInfo={info} providerDetails={details} />
|
|
||||||
})
|
|
||||||
.add('Connection Error', () => {
|
|
||||||
const provider = 'Metamask'
|
|
||||||
const userAddress = '0x873faa4cddd5b157e8e5a57e7a5479afc5d30moe'
|
|
||||||
const network = 'RINKEBY'
|
|
||||||
const info = <ProviderAccesible provider={provider} network={network} userAddress={userAddress} connected={false} />
|
|
||||||
const details = <UserDetails provider={provider} network={network} userAddress={userAddress} connected={false} />
|
|
||||||
|
|
||||||
return <Layout providerInfo={info} providerDetails={details} />
|
|
||||||
})
|
|
@ -1,11 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import Component from './index'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Components', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('Loader', () => <Component />)
|
|
@ -3,6 +3,7 @@ import * as React from 'react'
|
|||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import Modal from '@material-ui/core/Modal'
|
import Modal from '@material-ui/core/Modal'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import { sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
@ -27,7 +28,7 @@ const styles = () => ({
|
|||||||
top: '120px',
|
top: '120px',
|
||||||
width: '500px',
|
width: '500px',
|
||||||
height: '530px',
|
height: '530px',
|
||||||
borderRadius: '8px',
|
borderRadius: sm,
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#ffffff',
|
||||||
boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)',
|
boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)',
|
||||||
'&:focus': {
|
'&:focus': {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import classNames from 'classnames'
|
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import Table from '@material-ui/core/Table'
|
import Table from '@material-ui/core/Table'
|
||||||
import TableBody from '@material-ui/core/TableBody'
|
import TableBody from '@material-ui/core/TableBody'
|
||||||
@ -10,7 +9,7 @@ import TablePagination from '@material-ui/core/TablePagination'
|
|||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import { type Order, stableSort, getSorting } from '~/components/Table/sorting'
|
import { type Order, stableSort, getSorting } from '~/components/Table/sorting'
|
||||||
import TableHead, { type Column } from '~/components/Table/TableHead'
|
import TableHead, { type Column } from '~/components/Table/TableHead'
|
||||||
import { xl } from '~/theme/variables'
|
import { xxl, xl, sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props<K> = {
|
type Props<K> = {
|
||||||
label: string,
|
label: string,
|
||||||
@ -39,11 +38,12 @@ type State = {
|
|||||||
const styles = {
|
const styles = {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
borderRadius: '8px',
|
borderTopRightRadius: sm,
|
||||||
|
borderTopLeftRadius: sm,
|
||||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
selectRoot: {
|
selectRoot: {
|
||||||
lineHeight: '40px',
|
lineHeight: xxl,
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
},
|
},
|
||||||
white: {
|
white: {
|
||||||
@ -53,14 +53,11 @@ const styles = {
|
|||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
marginBottom: xl,
|
marginBottom: xl,
|
||||||
borderRadius: '8px',
|
borderBottomRightRadius: sm,
|
||||||
borderTopLeftRadius: 0,
|
borderBottomLeftRadius: sm,
|
||||||
borderTopRightRadius: 0,
|
|
||||||
},
|
},
|
||||||
loader: {
|
loader: {
|
||||||
alignItems: 'center',
|
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +122,13 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
|||||||
|
|
||||||
getEmptyStyle = (emptyRows: number) => ({
|
getEmptyStyle = (emptyRows: number) => ({
|
||||||
height: FIXED_HEIGHT * emptyRows,
|
height: FIXED_HEIGHT * emptyRows,
|
||||||
|
borderTopRightRadius: sm,
|
||||||
|
borderTopLeftRadius: sm,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
})
|
})
|
||||||
|
|
||||||
handleChangePage = (e: SyntheticInputEvent<HTMLInputElement>, page: number) => {
|
handleChangePage = (e: SyntheticInputEvent<HTMLInputElement>, page: number) => {
|
||||||
@ -171,7 +175,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
|||||||
sortedData = sortedData.slice(page * displayRows, page * displayRows + displayRows)
|
sortedData = sortedData.slice(page * displayRows, page * displayRows + displayRows)
|
||||||
}
|
}
|
||||||
|
|
||||||
const emptyRows = displayRows - Math.min(displayRows, data.length - page * displayRows)
|
const emptyRows = displayRows - Math.min(displayRows, data.size - page * displayRows)
|
||||||
const isEmpty = size === 0
|
const isEmpty = size === 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -184,7 +188,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
|||||||
)}
|
)}
|
||||||
{isEmpty && (
|
{isEmpty && (
|
||||||
<Row
|
<Row
|
||||||
className={classNames(classes.loader, !noBorder && classes.root)}
|
className={classes.loader}
|
||||||
style={this.getEmptyStyle(emptyRows + 1)}
|
style={this.getEmptyStyle(emptyRows + 1)}
|
||||||
>
|
>
|
||||||
<CircularProgress size={60} />
|
<CircularProgress size={60} />
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import { host } from 'storybook-host'
|
|
||||||
import Component from './index'
|
|
||||||
|
|
||||||
storiesOf('Components', module)
|
|
||||||
.addDecorator(
|
|
||||||
host({
|
|
||||||
title: 'Hairline',
|
|
||||||
align: 'center',
|
|
||||||
height: 5,
|
|
||||||
width: '100%',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.add('Hairline', () => <Component />)
|
|
@ -17,6 +17,7 @@ import ErrorIcon from './assets/error.svg'
|
|||||||
import InfoIcon from './assets/info.svg'
|
import InfoIcon from './assets/info.svg'
|
||||||
import CookiesBanner from '~/components/CookiesBanner'
|
import CookiesBanner from '~/components/CookiesBanner'
|
||||||
import styles from './index.scss'
|
import styles from './index.scss'
|
||||||
|
import { fontColor } from '~/theme/variables'
|
||||||
|
|
||||||
const notificationStyles = {
|
const notificationStyles = {
|
||||||
success: {
|
success: {
|
||||||
@ -24,7 +25,7 @@ const notificationStyles = {
|
|||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
lineHeight: 1.43,
|
lineHeight: 1.43,
|
||||||
color: '#001428',
|
color: fontColor,
|
||||||
minHeight: '58px',
|
minHeight: '58px',
|
||||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
@ -33,7 +34,7 @@ const notificationStyles = {
|
|||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
lineHeight: 1.43,
|
lineHeight: 1.43,
|
||||||
color: '#001428',
|
color: fontColor,
|
||||||
minHeight: '58px',
|
minHeight: '58px',
|
||||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
@ -42,7 +43,7 @@ const notificationStyles = {
|
|||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
lineHeight: 1.43,
|
lineHeight: 1.43,
|
||||||
color: '#001428',
|
color: fontColor,
|
||||||
minHeight: '58px',
|
minHeight: '58px',
|
||||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
@ -51,7 +52,7 @@ const notificationStyles = {
|
|||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
lineHeight: 1.43,
|
lineHeight: 1.43,
|
||||||
color: '#001428',
|
color: fontColor,
|
||||||
minHeight: '58px',
|
minHeight: '58px',
|
||||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,7 @@ export const decodeParamsFromSafeMethod = async (data: string) => {
|
|||||||
case '0xe318b52b':
|
case '0xe318b52b':
|
||||||
return {
|
return {
|
||||||
methodName: METHOD_TO_ID[methodId],
|
methodName: METHOD_TO_ID[methodId],
|
||||||
args: web3.eth.abi.decodeParameters(['address', 'address', 'address'], params),
|
args: web3.eth.abi.decodeParameters(['uint', 'address', 'address'], params),
|
||||||
}
|
}
|
||||||
|
|
||||||
// addOwnerWithThreshold
|
// addOwnerWithThreshold
|
||||||
|
@ -13,10 +13,15 @@ export const sameAddress = (firstAddress: string, secondAddress: string): boolea
|
|||||||
return firstAddress.toLowerCase() === secondAddress.toLowerCase()
|
return firstAddress.toLowerCase() === secondAddress.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shortVersionOf = (address: string, cut: number) => {
|
export const shortVersionOf = (value: string, cut: number) => {
|
||||||
const final = 42 - cut
|
if (!value) {
|
||||||
|
return 'Unknown'
|
||||||
|
}
|
||||||
|
|
||||||
if (!address) return 'Unknown address'
|
const final = value.length - cut
|
||||||
if (address.length < final) return address
|
if (value.length < final) {
|
||||||
return `${address.substring(0, cut)}...${address.substring(final)}`
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${value.substring(0, cut)}...${value.substring(final)}`
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import ReviewInformation from '~/routes/load/components/ReviewInformation'
|
|||||||
import OwnerList from '~/routes/load/components/OwnerList'
|
import OwnerList from '~/routes/load/components/OwnerList'
|
||||||
import DetailsForm, { safeFieldsValidation } from '~/routes/load/components/DetailsForm'
|
import DetailsForm, { safeFieldsValidation } from '~/routes/load/components/DetailsForm'
|
||||||
import { history } from '~/store'
|
import { history } from '~/store'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary, sm } from '~/theme/variables'
|
||||||
import { type SelectorProps } from '~/routes/load/container/selector'
|
import { type SelectorProps } from '~/routes/load/container/selector'
|
||||||
|
|
||||||
const getSteps = () => ['Name and address', 'Owners', 'Review']
|
const getSteps = () => ['Name and address', 'Owners', 'Review']
|
||||||
@ -21,7 +21,7 @@ export type LayoutProps = SelectorProps & {
|
|||||||
|
|
||||||
const iconStyle = {
|
const iconStyle = {
|
||||||
color: secondary,
|
color: secondary,
|
||||||
padding: '8px',
|
padding: sm,
|
||||||
marginRight: '5px',
|
marginRight: '5px',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import SafeNameField from '~/routes/open/components/SafeNameForm'
|
|||||||
import SafeOwnersFields from '~/routes/open/components/SafeOwnersConfirmationsForm'
|
import SafeOwnersFields from '~/routes/open/components/SafeOwnersConfirmationsForm'
|
||||||
import { getOwnerNameBy, getOwnerAddressBy, FIELD_CONFIRMATIONS } from '~/routes/open/components/fields'
|
import { getOwnerNameBy, getOwnerAddressBy, FIELD_CONFIRMATIONS } from '~/routes/open/components/fields'
|
||||||
import { history } from '~/store'
|
import { history } from '~/store'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary, sm } from '~/theme/variables'
|
||||||
|
|
||||||
const getSteps = () => ['Name', 'Owners and confirmations', 'Review']
|
const getSteps = () => ['Name', 'Owners and confirmations', 'Review']
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ type Props = {
|
|||||||
|
|
||||||
const iconStyle = {
|
const iconStyle = {
|
||||||
color: secondary,
|
color: secondary,
|
||||||
padding: '8px',
|
padding: sm,
|
||||||
marginRight: '5px',
|
marginRight: '5px',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import { State, Store } from '@sambego/storybook-state'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import { getAccountsFrom, getThresholdFrom } from '~/routes/open/utils/safeDataExtractor'
|
|
||||||
import { getProviderInfo } from '~/logic/wallets/getWeb3'
|
|
||||||
import { sleep } from '~/utils/timer'
|
|
||||||
import Component from './Layout'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
const store = new Store({
|
|
||||||
safeAddress: '',
|
|
||||||
safeTx: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
storiesOf('Routes /open', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('Open Safe with all props set', () => {
|
|
||||||
getProviderInfo()
|
|
||||||
const provider = 'METAMASK'
|
|
||||||
const userAccount = '0x03db1a8b26d08df23337e9276a36b474510f0023'
|
|
||||||
const onCallSafeContractSubmit = async (values: Object): Promise<void> => {
|
|
||||||
const accounts = getAccountsFrom(values)
|
|
||||||
const numConfirmations = getThresholdFrom(values)
|
|
||||||
const data = {
|
|
||||||
userAccount,
|
|
||||||
accounts,
|
|
||||||
requiredConfirmations: numConfirmations,
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(`Generating and sending a eth tx based on: ${JSON.stringify(data, null, 2)}`)
|
|
||||||
|
|
||||||
await sleep(3000)
|
|
||||||
|
|
||||||
store.set({
|
|
||||||
safeAddress: '0x03db1a8b26d08df23337e9276a36b474510f0025',
|
|
||||||
// eslint-disable-next-line
|
|
||||||
safeTx: {
|
|
||||||
transactionHash: '0x4603de1ab6a92b4ee1fd67189089f5c02f5df5d135bf85af84083c27808c0544',
|
|
||||||
transactionIndex: 0,
|
|
||||||
blockHash: '0x593ce7d85fef2a492e8f759f485c8b66ff803773e77182c68dd45c439b7a956d',
|
|
||||||
blockNumber: 19,
|
|
||||||
gasUsed: 3034193,
|
|
||||||
cumulativeGasUsed: 3034193,
|
|
||||||
contractAddress: '0xfddda33736fb95b587cbfecc1ff4a50f717adc00',
|
|
||||||
logs: [],
|
|
||||||
status: '0x01',
|
|
||||||
logsBloom:
|
|
||||||
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<State store={store}>
|
|
||||||
<Component
|
|
||||||
network="rinkeby"
|
|
||||||
provider={provider}
|
|
||||||
userAccount={userAccount}
|
|
||||||
safeAddress={store.get('safeAddress')}
|
|
||||||
safeTx={store.get('safeTx')}
|
|
||||||
onCallSafeContractSubmit={onCallSafeContractSubmit}
|
|
||||||
/>
|
|
||||||
</State>
|
|
||||||
)
|
|
||||||
})
|
|
@ -1,19 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import { ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3'
|
|
||||||
import Component from './component'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Routes /opening', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('View while Safe is being deployed', () => (
|
|
||||||
<Component
|
|
||||||
name="Super Vault 2000"
|
|
||||||
tx="0xed163e50e2e85695f5edafeba51d6be1758549858d12611ed4dcc96feaa19fc9"
|
|
||||||
network={ETHEREUM_NETWORK.RINKEBY}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
.add('Load this view without a tx', () => <Component network={ETHEREUM_NETWORK.UNKNOWN} />)
|
|
@ -26,8 +26,8 @@ const styles = () => ({
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
},
|
},
|
||||||
close: {
|
close: {
|
||||||
height: '24px',
|
height: lg,
|
||||||
width: '24px',
|
width: lg,
|
||||||
fill: secondaryText,
|
fill: secondaryText,
|
||||||
},
|
},
|
||||||
qrContainer: {
|
qrContainer: {
|
||||||
@ -48,7 +48,7 @@ const styles = () => ({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,7 @@ const styles = () => ({
|
|||||||
maxHeight: '75px',
|
maxHeight: '75px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
@ -31,7 +31,7 @@ const styles = () => ({
|
|||||||
buttonColumn: {
|
buttonColumn: {
|
||||||
padding: '52px 0',
|
padding: '52px 0',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -23,6 +23,7 @@ import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers'
|
|||||||
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||||
import ArrowDown from '../assets/arrow-down.svg'
|
import ArrowDown from '../assets/arrow-down.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
import { sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
@ -106,7 +107,7 @@ const ReviewCustomTx = ({
|
|||||||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||||
<Row margin="md">
|
<Row margin="md">
|
||||||
<Col xs={1}>
|
<Col xs={1}>
|
||||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={11} center="xs" layout="column">
|
<Col xs={11} center="xs" layout="column">
|
||||||
<Hairline />
|
<Hairline />
|
||||||
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
@ -50,7 +50,7 @@ export const styles = () => ({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
submitButton: {
|
submitButton: {
|
||||||
|
@ -28,6 +28,7 @@ import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions'
|
|||||||
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
||||||
import ArrowDown from '../assets/arrow-down.svg'
|
import ArrowDown from '../assets/arrow-down.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
import { sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
@ -136,7 +137,7 @@ const ReviewTx = ({
|
|||||||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||||
<Row margin="md">
|
<Row margin="md">
|
||||||
<Col xs={1}>
|
<Col xs={1}>
|
||||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={11} center="xs" layout="column">
|
<Col xs={11} center="xs" layout="column">
|
||||||
<Hairline />
|
<Hairline />
|
||||||
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
@ -37,7 +37,7 @@ export const styles = () => ({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
submitButton: {
|
submitButton: {
|
||||||
|
@ -25,6 +25,7 @@ import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo'
|
|||||||
import QRIcon from '~/assets/icons/qrcode.svg'
|
import QRIcon from '~/assets/icons/qrcode.svg'
|
||||||
import ArrowDown from '../assets/arrow-down.svg'
|
import ArrowDown from '../assets/arrow-down.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
import { sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
@ -102,7 +103,7 @@ const SendCustomTx = ({
|
|||||||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||||
<Row margin="md">
|
<Row margin="md">
|
||||||
<Col xs={1}>
|
<Col xs={1}>
|
||||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={11} center="xs" layout="column">
|
<Col xs={11} center="xs" layout="column">
|
||||||
<Hairline />
|
<Hairline />
|
||||||
|
@ -15,7 +15,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
@ -32,7 +32,7 @@ export const styles = () => ({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
submitButton: {
|
submitButton: {
|
||||||
|
@ -28,6 +28,7 @@ import ScanQRModal from '~/components/ScanQRModal'
|
|||||||
import ArrowDown from '../assets/arrow-down.svg'
|
import ArrowDown from '../assets/arrow-down.svg'
|
||||||
import QRIcon from '~/assets/icons/qrcode.svg'
|
import QRIcon from '~/assets/icons/qrcode.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
import { sm } from '~/theme/variables'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
@ -114,7 +115,7 @@ const SendFunds = ({
|
|||||||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||||
<Row margin="md">
|
<Row margin="md">
|
||||||
<Col xs={1}>
|
<Col xs={1}>
|
||||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={11} center="xs" layout="column">
|
<Col xs={11} center="xs" layout="column">
|
||||||
<Hairline />
|
<Hairline />
|
||||||
|
@ -15,7 +15,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
@ -32,7 +32,7 @@ export const styles = () => ({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
'& > button': {
|
'& > button': {
|
||||||
fontFamily: 'Averta',
|
fontFamily: 'Averta',
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
submitButton: {
|
submitButton: {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { lg } from '~/theme/variables'
|
import { lg, md } from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
title: {
|
title: {
|
||||||
padding: `${lg} 0 20px`,
|
padding: `${lg} 0 20px`,
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
formContainer: {
|
formContainer: {
|
||||||
padding: '0 20px',
|
padding: '0 20px',
|
||||||
|
@ -63,6 +63,11 @@ class Balances extends React.Component<Props, State> {
|
|||||||
props.fetchTokens()
|
props.fetchTokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
const { activateTokensByBalance, safeAddress } = this.props
|
||||||
|
activateTokensByBalance(safeAddress)
|
||||||
|
}
|
||||||
|
|
||||||
onShow = (action: Action) => () => {
|
onShow = (action: Action) => () => {
|
||||||
this.setState(() => ({ [`show${action}`]: true }))
|
this.setState(() => ({ [`show${action}`]: true }))
|
||||||
}
|
}
|
||||||
@ -89,17 +94,6 @@ class Balances extends React.Component<Props, State> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
|
|
||||||
const { checked } = e.target
|
|
||||||
|
|
||||||
this.setState(() => ({ hideZero: checked }))
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
const { activateTokensByBalance, safeAddress } = this.props
|
|
||||||
activateTokensByBalance(safeAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
showToken, showReceive, sendFunds,
|
showToken, showReceive, sendFunds,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { sm, md } from '~/theme/variables'
|
import { xs, sm, md } from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = (theme: Object) => ({
|
export const styles = (theme: Object) => ({
|
||||||
root: {
|
root: {
|
||||||
@ -41,7 +41,7 @@ export const styles = (theme: Object) => ({
|
|||||||
width: '95px',
|
width: '95px',
|
||||||
minWidth: '95px',
|
minWidth: '95px',
|
||||||
marginLeft: sm,
|
marginLeft: sm,
|
||||||
borderRadius: '4px',
|
borderRadius: xs,
|
||||||
'& > span': {
|
'& > span': {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
},
|
},
|
||||||
@ -49,7 +49,7 @@ export const styles = (theme: Object) => ({
|
|||||||
send: {
|
send: {
|
||||||
width: '75px',
|
width: '75px',
|
||||||
minWidth: '75px',
|
minWidth: '75px',
|
||||||
borderRadius: '4px',
|
borderRadius: xs,
|
||||||
'& > span': {
|
'& > span': {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
},
|
},
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import { List } from 'immutable'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import Component from './Layout'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Routes /safe:address', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('Safe undefined being connected', () => (
|
|
||||||
<Component userAddress="foo" safe={undefined} provider="METAMASK" activeTokens={List([])} fetchBalance={() => {}} />
|
|
||||||
))
|
|
||||||
.add('Safe undefined NOT connected', () => (
|
|
||||||
<Component userAddress="foo" safe={undefined} provider="" activeTokens={List([])} fetchBalance={() => {}} />
|
|
||||||
))
|
|
@ -1,11 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import Component from './index.jsx'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Components', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('NoRights', () => <Component />)
|
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||||||
lineHeight: 'normal',
|
lineHeight: 'normal',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||||||
lineHeight: 'normal',
|
lineHeight: 'normal',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -17,14 +17,14 @@ export const styles = () => ({
|
|||||||
lineHeight: 'normal',
|
lineHeight: 'normal',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
width: '35px',
|
width: '35px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
formContainer: {
|
formContainer: {
|
||||||
padding: `${md} ${lg}`,
|
padding: `${md} ${lg}`,
|
||||||
|
@ -10,7 +10,7 @@ export const styles = () => ({
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
padding: `${md} ${lg}`,
|
padding: `${md} ${lg}`,
|
||||||
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
address: {
|
address: {
|
||||||
marginRight: sm,
|
marginRight: sm,
|
||||||
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -17,14 +17,14 @@ export const styles = () => ({
|
|||||||
marginLeft: '20px',
|
marginLeft: '20px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
width: '35px',
|
width: '35px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '16px',
|
fontSize: md,
|
||||||
},
|
},
|
||||||
formContainer: {
|
formContainer: {
|
||||||
padding: `${md} ${lg}`,
|
padding: `${md} ${lg}`,
|
||||||
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||||||
marginRight: sm,
|
marginRight: sm,
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||||||
lineHeight: 'normal',
|
lineHeight: 'normal',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
address: {
|
address: {
|
||||||
marginRight: sm,
|
marginRight: sm,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { lg } from '~/theme/variables'
|
import { lg, sm } from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
formContainer: {
|
formContainer: {
|
||||||
@ -40,7 +40,7 @@ export const styles = () => ({
|
|||||||
controlsRow: {
|
controlsRow: {
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
padding: lg,
|
padding: lg,
|
||||||
borderRadius: '8px',
|
borderRadius: sm,
|
||||||
},
|
},
|
||||||
removeOwnerIcon: {
|
removeOwnerIcon: {
|
||||||
marginLeft: lg,
|
marginLeft: lg,
|
||||||
|
@ -18,11 +18,11 @@ import Link from '~/components/layout/Link'
|
|||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
import Hairline from '~/components/layout/Hairline'
|
||||||
import actions, { type Actions } from './actions'
|
import actions, { type Actions } from './actions'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary, md } from '~/theme/variables'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: md,
|
||||||
color: secondary,
|
color: secondary,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export const styles = () => ({
|
|||||||
minHeight: '369px',
|
minHeight: '369px',
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
close: {
|
close: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
fontColor, lg, smallFontSize, border, secondaryText,
|
fontColor, xl, lg, smallFontSize, border, secondaryText,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
@ -24,7 +24,7 @@ export const styles = () => ({
|
|||||||
borderTop: `2px solid ${border}`,
|
borderTop: `2px solid ${border}`,
|
||||||
},
|
},
|
||||||
modifyBtn: {
|
modifyBtn: {
|
||||||
height: '32px',
|
height: xl,
|
||||||
fontSize: smallFontSize,
|
fontSize: smallFontSize,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@ export const styles = () => ({
|
|||||||
minHeight: '505px',
|
minHeight: '505px',
|
||||||
marginBottom: '54px',
|
marginBottom: '54px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
borderRadius: '8px',
|
borderRadius: sm,
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
letterSpacing: '-0.5px',
|
letterSpacing: '-0.5px',
|
||||||
@ -25,7 +25,7 @@ export const styles = () => ({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:first-child': {
|
'&:first-child': {
|
||||||
borderTopLeftRadius: '8px',
|
borderTopLeftRadius: sm,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
active: {
|
active: {
|
||||||
@ -57,7 +57,7 @@ export const styles = () => ({
|
|||||||
},
|
},
|
||||||
removeSafeIcon: {
|
removeSafeIcon: {
|
||||||
marginLeft: sm,
|
marginLeft: sm,
|
||||||
height: '16px',
|
height: md,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import Bold from '~/components/layout/Bold'
|
|
||||||
import Col from '~/components/layout/Col'
|
|
||||||
import Row from '~/components/layout/Row'
|
|
||||||
import Paragraph from '~/components/layout/Paragraph/index'
|
|
||||||
|
|
||||||
export const NO_TRANSACTION_ROW_TEST_ID = 'no-transaction-row'
|
|
||||||
|
|
||||||
const NoTransactions = () => (
|
|
||||||
<Row data-testid={NO_TRANSACTION_ROW_TEST_ID}>
|
|
||||||
<Col xs={12} center="xs" sm={10} smOffset={2} start="sm" margin="md">
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>No transactions found for this Safe</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default NoTransactions
|
|
@ -11,7 +11,7 @@ export const styles = () => ({
|
|||||||
maxHeight: '75px',
|
maxHeight: '75px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -11,7 +11,7 @@ export const styles = () => ({
|
|||||||
maxHeight: '75px',
|
maxHeight: '75px',
|
||||||
},
|
},
|
||||||
headingText: {
|
headingText: {
|
||||||
fontSize: '24px',
|
fontSize: lg,
|
||||||
},
|
},
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
|
@ -1,36 +1,25 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import EditIcon from '@material-ui/icons/Edit'
|
|
||||||
import BlockIcon from '@material-ui/icons/Block'
|
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import { sm, lg, background } from '~/theme/variables'
|
import { xl, sm, border } from '~/theme/variables'
|
||||||
|
|
||||||
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
|
||||||
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onTxConfirm: Function,
|
|
||||||
onTxCancel: Function,
|
|
||||||
onTxExecute: Function,
|
|
||||||
classes: Object,
|
classes: Object,
|
||||||
showConfirmBtn: boolean,
|
onTxCancel: Function,
|
||||||
showCancelBtn: boolean,
|
showCancelBtn: boolean,
|
||||||
showExecuteBtn: boolean,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = () => ({
|
const styles = () => ({
|
||||||
buttonRow: {
|
buttonRow: {
|
||||||
height: '56px',
|
borderTop: `2px solid ${border}`,
|
||||||
justifyContent: 'center',
|
display: 'flex',
|
||||||
backgroundColor: background,
|
justifyContent: 'flex-end',
|
||||||
|
padding: '10px 20px',
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
height: '32px',
|
height: xl,
|
||||||
'&:last-child': {
|
|
||||||
marginLeft: lg,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
width: '14px',
|
width: '14px',
|
||||||
@ -42,46 +31,12 @@ const styles = () => ({
|
|||||||
const ButtonRow = ({
|
const ButtonRow = ({
|
||||||
classes,
|
classes,
|
||||||
onTxCancel,
|
onTxCancel,
|
||||||
onTxConfirm,
|
|
||||||
showConfirmBtn,
|
|
||||||
showCancelBtn,
|
showCancelBtn,
|
||||||
showExecuteBtn,
|
|
||||||
onTxExecute,
|
|
||||||
}: Props) => (
|
}: Props) => (
|
||||||
<Row align="center" className={classes.buttonRow}>
|
<Row align="right" className={classes.buttonRow}>
|
||||||
{showCancelBtn && (
|
{showCancelBtn && (
|
||||||
<Button className={classes.button} variant="contained" minWidth={140} color="secondary" onClick={onTxCancel}>
|
<Button className={classes.button} variant="contained" minWidth={140} color="secondary" onClick={onTxCancel}>
|
||||||
<BlockIcon className={classes.icon} />
|
Cancel tx
|
||||||
{' '}
|
|
||||||
Cancel TX
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{showConfirmBtn && (
|
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
variant="contained"
|
|
||||||
minWidth={140}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxConfirm}
|
|
||||||
testId={CONFIRM_TX_BTN_TEST_ID}
|
|
||||||
>
|
|
||||||
<EditIcon className={classes.icon} />
|
|
||||||
{' '}
|
|
||||||
Confirm TX
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{showExecuteBtn && (
|
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
variant="contained"
|
|
||||||
minWidth={140}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxExecute}
|
|
||||||
testId={EXECUTE_TX_BTN_TEST_ID}
|
|
||||||
>
|
|
||||||
<EditIcon className={classes.icon} />
|
|
||||||
{' '}
|
|
||||||
Execute TX
|
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import React from 'react'
|
|
||||||
import { List } from 'immutable'
|
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
|
||||||
import MuiList from '@material-ui/core/List'
|
|
||||||
import ListItem from '@material-ui/core/ListItem'
|
|
||||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
|
||||||
import ListItemText from '@material-ui/core/ListItemText'
|
|
||||||
import Chip from '@material-ui/core/Chip'
|
|
||||||
import Identicon from '~/components/Identicon'
|
|
||||||
import Hairline from '~/components/layout/Hairline'
|
|
||||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
|
||||||
import { secondary } from '~/theme/variables'
|
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
|
||||||
import { styles } from './style'
|
|
||||||
|
|
||||||
type ListProps = {
|
|
||||||
owners: List<Owner>,
|
|
||||||
classes: Object,
|
|
||||||
executionConfirmation?: Owner,
|
|
||||||
}
|
|
||||||
|
|
||||||
type OwnerProps = {
|
|
||||||
owner: Owner,
|
|
||||||
classes: Object,
|
|
||||||
isExecutor?: boolean,
|
|
||||||
}
|
|
||||||
|
|
||||||
const openIconStyle = {
|
|
||||||
height: '13px',
|
|
||||||
color: secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
const OwnerComponent = withStyles(styles)(({ owner, classes, isExecutor }: OwnerProps) => (
|
|
||||||
<ListItem key={owner.address} className={classes.owner}>
|
|
||||||
<ListItemIcon>
|
|
||||||
<Identicon address={owner.address} diameter={32} className={classes.icon} />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
primary={owner.name}
|
|
||||||
secondary={(
|
|
||||||
<a href={getEtherScanLink('address', owner.address)} target="_blank" rel="noopener noreferrer">
|
|
||||||
{shortVersionOf(owner.address, 4)}
|
|
||||||
{' '}
|
|
||||||
<OpenInNew style={openIconStyle} />
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{isExecutor && <Chip label="EXECUTOR" color="secondary" />}
|
|
||||||
</ListItem>
|
|
||||||
))
|
|
||||||
|
|
||||||
const OwnersList = ({ owners, classes, executionConfirmation }: ListProps) => (
|
|
||||||
<>
|
|
||||||
<MuiList className={classes.ownersList}>
|
|
||||||
{executionConfirmation && <OwnerComponent owner={executionConfirmation} isExecutor />}
|
|
||||||
{owners.map((owner) => (
|
|
||||||
<OwnerComponent key={owner.address} owner={owner} />
|
|
||||||
))}
|
|
||||||
</MuiList>
|
|
||||||
<Hairline color="#d4d53d" />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default withStyles(styles)(OwnersList)
|
|
@ -0,0 +1,92 @@
|
|||||||
|
// @flow
|
||||||
|
import React from 'react'
|
||||||
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import Button from '~/components/layout/Button'
|
||||||
|
import Img from '~/components/layout/Img'
|
||||||
|
import EtherscanLink from '~/components/EtherscanLink'
|
||||||
|
import Identicon from '~/components/Identicon'
|
||||||
|
import Block from '~/components/layout/Block'
|
||||||
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
|
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||||
|
import { styles } from './style'
|
||||||
|
import ConfirmSmallGreyIcon from './assets/confirm-small-grey.svg'
|
||||||
|
import ConfirmSmallGreenIcon from './assets/confirm-small-green.svg'
|
||||||
|
import ConfirmSmallFilledIcon from './assets/confirm-small-filled.svg'
|
||||||
|
|
||||||
|
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
||||||
|
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
||||||
|
|
||||||
|
type OwnerProps = {
|
||||||
|
owner: Owner,
|
||||||
|
classes: Object,
|
||||||
|
userAddress: string,
|
||||||
|
confirmed?: boolean,
|
||||||
|
executor?: string,
|
||||||
|
thresholdReached: boolean,
|
||||||
|
showConfirmBtn: boolean,
|
||||||
|
showExecuteBtn: boolean,
|
||||||
|
onTxConfirm: Function,
|
||||||
|
onTxExecute: Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
const OwnerComponent = ({
|
||||||
|
owner,
|
||||||
|
userAddress,
|
||||||
|
classes,
|
||||||
|
onTxConfirm,
|
||||||
|
showConfirmBtn,
|
||||||
|
showExecuteBtn,
|
||||||
|
onTxExecute,
|
||||||
|
executor,
|
||||||
|
confirmed,
|
||||||
|
thresholdReached,
|
||||||
|
}: OwnerProps) => (
|
||||||
|
<Block className={classes.container}>
|
||||||
|
<div className={confirmed || thresholdReached || executor
|
||||||
|
? classes.verticalLineProgressDone
|
||||||
|
: classes.verticalLineProgressPending}
|
||||||
|
/>
|
||||||
|
<div className={classes.iconState}>
|
||||||
|
{confirmed
|
||||||
|
? <Img src={ConfirmSmallFilledIcon} />
|
||||||
|
: thresholdReached || executor ? <Img src={ConfirmSmallGreenIcon} /> : <Img src={ConfirmSmallGreyIcon} />}
|
||||||
|
</div>
|
||||||
|
<Identicon address={owner.address} diameter={32} className={classes.icon} />
|
||||||
|
<Block>
|
||||||
|
<Paragraph className={classes.name} noMargin>
|
||||||
|
{owner.name}
|
||||||
|
</Paragraph>
|
||||||
|
<EtherscanLink className={classes.address} type="address" value={owner.address} cut={4} />
|
||||||
|
</Block>
|
||||||
|
<Block className={classes.spacer} />
|
||||||
|
{showConfirmBtn && owner.address === userAddress && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxConfirm}
|
||||||
|
testId={CONFIRM_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
|
Confirm tx
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showExecuteBtn && owner.address === userAddress && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxExecute}
|
||||||
|
testId={EXECUTE_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
|
Execute tx
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{owner.address === executor && (
|
||||||
|
<Block className={classes.executor}>Executor</Block>
|
||||||
|
)}
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withStyles(styles)(OwnerComponent)
|
@ -0,0 +1,65 @@
|
|||||||
|
// @flow
|
||||||
|
import React from 'react'
|
||||||
|
import { List } from 'immutable'
|
||||||
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import OwnerComponent from './OwnerComponent'
|
||||||
|
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||||
|
import { styles } from './style'
|
||||||
|
|
||||||
|
type ListProps = {
|
||||||
|
ownersWhoConfirmed: List<Owner>,
|
||||||
|
ownersUnconfirmed: List<Owner>,
|
||||||
|
classes: Object,
|
||||||
|
userAddress: string,
|
||||||
|
executor: string,
|
||||||
|
thresholdReached: boolean,
|
||||||
|
showConfirmBtn: boolean,
|
||||||
|
showExecuteBtn: boolean,
|
||||||
|
onTxConfirm: Function,
|
||||||
|
onTxExecute: Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
const OwnersList = ({
|
||||||
|
userAddress,
|
||||||
|
ownersWhoConfirmed,
|
||||||
|
ownersUnconfirmed,
|
||||||
|
classes,
|
||||||
|
executor,
|
||||||
|
thresholdReached,
|
||||||
|
showConfirmBtn,
|
||||||
|
showExecuteBtn,
|
||||||
|
onTxConfirm,
|
||||||
|
onTxExecute,
|
||||||
|
}: ListProps) => (
|
||||||
|
<>
|
||||||
|
{ownersWhoConfirmed.map((owner) => (
|
||||||
|
<OwnerComponent
|
||||||
|
key={owner.address}
|
||||||
|
owner={owner}
|
||||||
|
classes={classes}
|
||||||
|
userAddress={userAddress}
|
||||||
|
executor={executor}
|
||||||
|
thresholdReached={thresholdReached}
|
||||||
|
confirmed
|
||||||
|
showExecuteBtn={showExecuteBtn}
|
||||||
|
onTxExecute={onTxExecute}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{ownersUnconfirmed.map((owner) => (
|
||||||
|
<OwnerComponent
|
||||||
|
key={owner.address}
|
||||||
|
owner={owner}
|
||||||
|
classes={classes}
|
||||||
|
userAddress={userAddress}
|
||||||
|
executor={executor}
|
||||||
|
thresholdReached={thresholdReached}
|
||||||
|
onTxConfirm={onTxConfirm}
|
||||||
|
showConfirmBtn={showConfirmBtn}
|
||||||
|
showExecuteBtn={showExecuteBtn}
|
||||||
|
onTxExecute={onTxExecute}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withStyles(styles)(OwnersList)
|
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path fill="#008C73" d="M10 0C4.489 0 0 4.489 0 10s4.489 10 10 10 10-4.489 10-10S15.511 0 10 0z"/>
|
||||||
|
<path fill="#FFF" d="M9.124 13.75L5 9.406l1.245-1.312 2.88 3.034 4.63-4.878L15 7.561z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 344 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||||
|
<circle cx="10" cy="10" r="9" fill="#FFFAF4" fill-rule="evenodd" stroke="#008C73" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 196 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||||
|
<circle cx="10" cy="10" r="9" fill="#FFFAF4" fill-rule="evenodd" stroke="#B2B5B2" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 196 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
|
||||||
|
<circle cx="5" cy="5" r="5" fill="#008C73" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 160 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
|
||||||
|
<circle cx="5" cy="5" r="4" fill="#FFFAF4" fill-rule="evenodd" stroke="#008C73" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 194 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
|
||||||
|
<circle cx="5" cy="5" r="4" fill="#FFFAF4" fill-rule="evenodd" stroke="#B2B5B2" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 194 B |
@ -1,18 +1,20 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
|
import cn from 'classnames'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import Tabs from '@material-ui/core/Tabs'
|
import Block from '~/components/layout/Block'
|
||||||
import Tab from '@material-ui/core/Tab'
|
|
||||||
import Col from '~/components/layout/Col'
|
import Col from '~/components/layout/Col'
|
||||||
import Row from '~/components/layout/Row'
|
import Img from '~/components/layout/Img'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
|
||||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||||
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions/send'
|
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions/send'
|
||||||
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
||||||
import OwnersList from './List'
|
import OwnersList from './OwnersList'
|
||||||
import ButtonRow from './ButtonRow'
|
import ButtonRow from './ButtonRow'
|
||||||
|
import CheckLargeFilledGreenIcon from './assets/check-large-filled-green.svg'
|
||||||
|
import ConfirmLargeGreenIcon from './assets/confirm-large-green.svg'
|
||||||
|
import ConfirmLargeGreyIcon from './assets/confirm-large-grey.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -29,7 +31,10 @@ type Props = {
|
|||||||
onTxExecute: Function,
|
onTxExecute: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCancellationTransaction = (tx: Transaction, safeAddress: string) => !tx.value && tx.data === EMPTY_DATA && tx.recipient === safeAddress
|
const isCancellationTransaction = (
|
||||||
|
tx: Transaction,
|
||||||
|
safeAddress: string,
|
||||||
|
) => !tx.value && tx.data === EMPTY_DATA && tx.recipient === safeAddress
|
||||||
|
|
||||||
const OwnersColumn = ({
|
const OwnersColumn = ({
|
||||||
tx,
|
tx,
|
||||||
@ -44,31 +49,26 @@ const OwnersColumn = ({
|
|||||||
onTxCancel,
|
onTxCancel,
|
||||||
onTxExecute,
|
onTxExecute,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [tabIndex, setTabIndex] = useState(0)
|
|
||||||
const handleTabChange = (event, tabClicked) => {
|
|
||||||
setTabIndex(tabClicked)
|
|
||||||
}
|
|
||||||
|
|
||||||
const cancellationTx = isCancellationTransaction(tx, safeAddress)
|
const cancellationTx = isCancellationTransaction(tx, safeAddress)
|
||||||
|
|
||||||
const ownersWhoConfirmed = []
|
const ownersWhoConfirmed = []
|
||||||
let currentUserAlreadyConfirmed = false
|
let currentUserAlreadyConfirmed = false
|
||||||
let executionConfirmation
|
|
||||||
|
|
||||||
tx.confirmations.forEach((conf) => {
|
tx.confirmations.forEach((conf) => {
|
||||||
if (conf.owner.address === userAddress) {
|
if (conf.owner.address === userAddress) {
|
||||||
currentUserAlreadyConfirmed = true
|
currentUserAlreadyConfirmed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.type === TX_TYPE_CONFIRMATION) {
|
if (conf.type === TX_TYPE_CONFIRMATION) {
|
||||||
ownersWhoConfirmed.push(conf.owner)
|
ownersWhoConfirmed.push(conf.owner)
|
||||||
} else {
|
|
||||||
executionConfirmation = conf.owner
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const ownersUnconfirmed = owners.filter(
|
const ownersUnconfirmed = owners.filter(
|
||||||
(owner) => tx.confirmations.findIndex((conf) => conf.owner.address === owner.address) === -1,
|
(owner) => tx.confirmations.findIndex((conf) => conf.owner.address === owner.address) === -1,
|
||||||
)
|
)
|
||||||
|
let userIsUnconfirmedOwner
|
||||||
|
ownersUnconfirmed.some((owner) => {
|
||||||
|
userIsUnconfirmedOwner = owner.address === userAddress
|
||||||
|
return userIsUnconfirmedOwner
|
||||||
|
})
|
||||||
|
|
||||||
let displayButtonRow = true
|
let displayButtonRow = true
|
||||||
if (tx.executionTxHash) {
|
if (tx.executionTxHash) {
|
||||||
@ -83,33 +83,51 @@ const OwnersColumn = ({
|
|||||||
displayButtonRow = false
|
displayButtonRow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let confirmedLabel = `Confirmed [${tx.confirmations.size}/${threshold}]`
|
const showConfirmBtn = !tx.isExecuted
|
||||||
if (tx.executionTxHash) {
|
&& !tx.cancelled
|
||||||
confirmedLabel = `Confirmed [${tx.confirmations.size}]`
|
&& userIsUnconfirmedOwner
|
||||||
}
|
&& !currentUserAlreadyConfirmed
|
||||||
const unconfirmedLabel = `Unconfirmed [${ownersUnconfirmed.size}]`
|
&& !thresholdReached
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col xs={6} className={classes.rightCol} layout="block">
|
<Col xs={6} className={classes.rightCol} layout="block">
|
||||||
<Row>
|
<Block className={cn(classes.ownerListTitle, (thresholdReached || tx.isExecuted) && classes.ownerListTitleDone)}>
|
||||||
<Tabs value={tabIndex} onChange={handleTabChange} indicatorColor="secondary" textColor="secondary">
|
<div className={classes.iconState}>
|
||||||
<Tab label={confirmedLabel} />
|
{thresholdReached || tx.isExecuted
|
||||||
<Tab label={unconfirmedLabel} />
|
? <Img src={CheckLargeFilledGreenIcon} />
|
||||||
</Tabs>
|
: <Img src={ConfirmLargeGreenIcon} />}
|
||||||
<Hairline color="#d4d53d" />
|
</div>
|
||||||
</Row>
|
{tx.isExecuted
|
||||||
<Row>
|
? `Confirmed [${tx.confirmations.size}/${tx.confirmations.size}]`
|
||||||
{tabIndex === 0 && <OwnersList owners={ownersWhoConfirmed} executionConfirmation={executionConfirmation} />}
|
: `Confirmed [${tx.confirmations.size}/${threshold}]`}
|
||||||
</Row>
|
</Block>
|
||||||
<Row>{tabIndex === 1 && <OwnersList owners={ownersUnconfirmed} />}</Row>
|
<OwnersList
|
||||||
|
userAddress={userAddress}
|
||||||
|
ownersWhoConfirmed={ownersWhoConfirmed}
|
||||||
|
ownersUnconfirmed={ownersUnconfirmed}
|
||||||
|
executor={tx.executor}
|
||||||
|
thresholdReached={thresholdReached}
|
||||||
|
onTxConfirm={onTxConfirm}
|
||||||
|
onTxExecute={onTxExecute}
|
||||||
|
showConfirmBtn={showConfirmBtn}
|
||||||
|
showExecuteBtn={!tx.isExecuted && thresholdReached}
|
||||||
|
/>
|
||||||
|
<Block className={cn(classes.ownerListTitle, tx.isExecuted && classes.ownerListTitleDone)}>
|
||||||
|
<div className={thresholdReached || tx.isExecuted
|
||||||
|
? classes.verticalLineProgressDone
|
||||||
|
: classes.verticalLineProgressPending}
|
||||||
|
/>
|
||||||
|
<div className={classes.iconState}>
|
||||||
|
{!thresholdReached && !tx.isExecuted && <Img src={ConfirmLargeGreyIcon} />}
|
||||||
|
{thresholdReached && !tx.isExecuted && <Img src={ConfirmLargeGreenIcon} />}
|
||||||
|
{tx.isExecuted && <Img src={CheckLargeFilledGreenIcon} />}
|
||||||
|
</div>
|
||||||
|
Executed
|
||||||
|
</Block>
|
||||||
{granted && displayButtonRow && (
|
{granted && displayButtonRow && (
|
||||||
<ButtonRow
|
<ButtonRow
|
||||||
onTxConfirm={onTxConfirm}
|
|
||||||
onTxCancel={onTxCancel}
|
onTxCancel={onTxCancel}
|
||||||
showConfirmBtn={!currentUserAlreadyConfirmed && !thresholdReached}
|
|
||||||
showCancelBtn={!cancellationTx}
|
showCancelBtn={!cancellationTx}
|
||||||
showExecuteBtn={thresholdReached}
|
|
||||||
onTxExecute={onTxExecute}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { border, sm } from '~/theme/variables'
|
import {
|
||||||
|
border, sm, boldFont, primary, secondary, secondaryText,
|
||||||
|
} from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
ownersList: {
|
ownersList: {
|
||||||
@ -10,7 +12,23 @@ export const styles = () => ({
|
|||||||
},
|
},
|
||||||
rightCol: {
|
rightCol: {
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
borderLeft: 'solid 1px #d4d53d',
|
borderLeft: `2px solid ${border}`,
|
||||||
|
},
|
||||||
|
verticalLineProgressPending: {
|
||||||
|
position: 'absolute',
|
||||||
|
borderLeft: `2px solid ${secondaryText}`,
|
||||||
|
height: '52px',
|
||||||
|
top: '-26px',
|
||||||
|
left: '29px',
|
||||||
|
zIndex: '10',
|
||||||
|
},
|
||||||
|
verticalLineProgressDone: {
|
||||||
|
position: 'absolute',
|
||||||
|
borderLeft: `2px solid ${secondary}`,
|
||||||
|
height: '52px',
|
||||||
|
top: '-26px',
|
||||||
|
left: '29px',
|
||||||
|
zIndex: '10',
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
marginRight: sm,
|
marginRight: sm,
|
||||||
@ -18,4 +36,57 @@ export const styles = () => ({
|
|||||||
owner: {
|
owner: {
|
||||||
borderBottom: `1px solid ${border}`,
|
borderBottom: `1px solid ${border}`,
|
||||||
},
|
},
|
||||||
|
container: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
padding: '5px 20px',
|
||||||
|
},
|
||||||
|
ownerListTitle: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: '15px',
|
||||||
|
paddingLeft: '20px',
|
||||||
|
fontSize: '11px',
|
||||||
|
fontWeight: boldFont,
|
||||||
|
lineHeight: 1.27,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '1px',
|
||||||
|
},
|
||||||
|
ownerListTitleDone: {
|
||||||
|
color: secondary,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
overflow: 'hidden',
|
||||||
|
height: '15px',
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
height: '20px',
|
||||||
|
},
|
||||||
|
spacer: {
|
||||||
|
flex: 'auto',
|
||||||
|
},
|
||||||
|
iconState: {
|
||||||
|
width: '20px',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginRight: '10px',
|
||||||
|
zIndex: '100',
|
||||||
|
'& > img': {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignSelf: 'center',
|
||||||
|
},
|
||||||
|
executor: {
|
||||||
|
borderRadius: '3px',
|
||||||
|
padding: '3px 5px',
|
||||||
|
background: border,
|
||||||
|
color: primary,
|
||||||
|
alignSelf: 'center',
|
||||||
|
fontSize: '11px',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
@ -50,7 +50,7 @@ type CustomDescProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProps) => (
|
const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProps) => (
|
||||||
<Paragraph noMargin data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
||||||
<Bold>
|
<Bold>
|
||||||
Send
|
Send
|
||||||
{' '}
|
{' '}
|
||||||
@ -60,33 +60,31 @@ const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProp
|
|||||||
{' '}
|
{' '}
|
||||||
to:
|
to:
|
||||||
</Bold>
|
</Bold>
|
||||||
<br />
|
|
||||||
<EtherscanLink type="address" value={recipient} />
|
<EtherscanLink type="address" value={recipient} />
|
||||||
</Paragraph>
|
</Block>
|
||||||
)
|
)
|
||||||
|
|
||||||
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
||||||
<>
|
<>
|
||||||
{removedOwner && (
|
{removedOwner && (
|
||||||
<Paragraph data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
||||||
<Bold>Remove owner:</Bold>
|
<Bold>Remove owner:</Bold>
|
||||||
<br />
|
|
||||||
<EtherscanLink type="address" value={removedOwner} />
|
<EtherscanLink type="address" value={removedOwner} />
|
||||||
</Paragraph>
|
</Block>
|
||||||
)}
|
)}
|
||||||
{addedOwner && (
|
{addedOwner && (
|
||||||
<Paragraph data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
||||||
<Bold>Add owner:</Bold>
|
<Bold>Add owner:</Bold>
|
||||||
<br />
|
|
||||||
<EtherscanLink type="address" value={addedOwner} />
|
<EtherscanLink type="address" value={addedOwner} />
|
||||||
</Paragraph>
|
</Block>
|
||||||
)}
|
)}
|
||||||
{newThreshold && (
|
{newThreshold && (
|
||||||
<Paragraph data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
||||||
<Bold>Change required confirmations:</Bold>
|
<Bold>Change required confirmations:</Bold>
|
||||||
<br />
|
<Paragraph size="md" noMargin>
|
||||||
{newThreshold}
|
{newThreshold}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
</Block>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@ -95,7 +93,7 @@ const CustomDescription = ({
|
|||||||
data, value = 0, recipient, classes,
|
data, value = 0, recipient, classes,
|
||||||
}: CustomDescProps) => (
|
}: CustomDescProps) => (
|
||||||
<>
|
<>
|
||||||
<Paragraph noMargin data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
||||||
<Bold>
|
<Bold>
|
||||||
Send
|
Send
|
||||||
{' '}
|
{' '}
|
||||||
@ -105,22 +103,21 @@ const CustomDescription = ({
|
|||||||
{' '}
|
{' '}
|
||||||
to:
|
to:
|
||||||
</Bold>
|
</Bold>
|
||||||
<br />
|
|
||||||
<EtherscanLink type="address" value={recipient} />
|
<EtherscanLink type="address" value={recipient} />
|
||||||
</Paragraph>
|
</Block>
|
||||||
<Paragraph className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
<Block className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
||||||
<Bold>Data (hex encoded):</Bold>
|
<Bold>Data (hex encoded):</Bold>
|
||||||
<br />
|
<Paragraph size="md" noMargin>
|
||||||
{data}
|
{data}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
</Block>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const TxDescription = ({ tx, classes }: Props) => {
|
const TxDescription = ({ tx, classes }: Props) => {
|
||||||
const {
|
const {
|
||||||
recipient, value, modifySettingsTx, removedOwner, addedOwner, newThreshold, cancellationTx, customTx, data,
|
recipient, value, modifySettingsTx, removedOwner, addedOwner, newThreshold, cancellationTx, customTx, creationTx, data,
|
||||||
} = getTxData(tx)
|
} = getTxData(tx)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block className={classes.txDataContainer}>
|
<Block className={classes.txDataContainer}>
|
||||||
{modifySettingsTx && (
|
{modifySettingsTx && (
|
||||||
@ -129,7 +126,7 @@ const TxDescription = ({ tx, classes }: Props) => {
|
|||||||
{customTx && (
|
{customTx && (
|
||||||
<CustomDescription data={data} value={value} recipient={recipient} classes={classes} />
|
<CustomDescription data={data} value={value} recipient={recipient} classes={classes} />
|
||||||
)}
|
)}
|
||||||
{!cancellationTx && !modifySettingsTx && !customTx && (
|
{!cancellationTx && !modifySettingsTx && !customTx && !creationTx && (
|
||||||
<TransferDescription value={value} symbol={tx.symbol} recipient={recipient} />
|
<TransferDescription value={value} symbol={tx.symbol} recipient={recipient} />
|
||||||
)}
|
)}
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -11,6 +11,7 @@ type DecodedTxData = {
|
|||||||
addedOwner?: string,
|
addedOwner?: string,
|
||||||
cancellationTx?: boolean,
|
cancellationTx?: boolean,
|
||||||
customTx?: boolean,
|
customTx?: boolean,
|
||||||
|
creationTx?: boolean,
|
||||||
data: string,
|
data: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +55,8 @@ export const getTxData = (tx: Transaction): DecodedTxData => {
|
|||||||
}
|
}
|
||||||
} else if (tx.cancellationTx) {
|
} else if (tx.cancellationTx) {
|
||||||
txData.cancellationTx = true
|
txData.cancellationTx = true
|
||||||
|
} else if (tx.creationTx) {
|
||||||
|
txData.creationTx = true
|
||||||
} else {
|
} else {
|
||||||
txData.recipient = tx.recipient
|
txData.recipient = tx.recipient
|
||||||
txData.value = 0
|
txData.value = 0
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Col from '~/components/layout/Col'
|
import Col from '~/components/layout/Col'
|
||||||
@ -10,11 +9,9 @@ import Bold from '~/components/layout/Bold'
|
|||||||
import Span from '~/components/layout/Span'
|
import Span from '~/components/layout/Span'
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
import Hairline from '~/components/layout/Hairline'
|
||||||
|
import EtherScanLink from '~/components/EtherscanLink'
|
||||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
|
||||||
import { secondary } from '~/theme/variables'
|
|
||||||
import TxDescription from './TxDescription'
|
import TxDescription from './TxDescription'
|
||||||
import OwnersColumn from './OwnersColumn'
|
import OwnersColumn from './OwnersColumn'
|
||||||
import CancelTxModal from './CancelTxModal'
|
import CancelTxModal from './CancelTxModal'
|
||||||
@ -36,16 +33,13 @@ type Props = {
|
|||||||
|
|
||||||
type OpenModal = 'cancelTx' | 'approveTx' | null
|
type OpenModal = 'cancelTx' | 'approveTx' | null
|
||||||
|
|
||||||
const openIconStyle = {
|
|
||||||
height: '13px',
|
|
||||||
color: secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
const txStatusToLabel = {
|
const txStatusToLabel = {
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
|
awaiting_your_confirmation: 'Awaiting your confirmation',
|
||||||
awaiting_confirmations: 'Awaiting confirmations',
|
awaiting_confirmations: 'Awaiting confirmations',
|
||||||
cancelled: 'Cancelled',
|
cancelled: 'Cancelled',
|
||||||
awaiting_execution: 'Awaiting execution',
|
awaiting_execution: 'Awaiting execution',
|
||||||
|
pending: 'Pending',
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExpandedTx = ({
|
const ExpandedTx = ({
|
||||||
@ -67,24 +61,21 @@ const ExpandedTx = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Block>
|
<Block className={classes.expandedTxBlock}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={6} layout="column">
|
<Col xs={6} layout="column">
|
||||||
<Block className={classes.txDataContainer}>
|
<Block className={classes.txDataContainer}>
|
||||||
<Paragraph noMargin>
|
<Block align="left" className={classes.txData}>
|
||||||
<Bold>TX hash: </Bold>
|
<Bold className={classes.txHash}>TX hash:</Bold>
|
||||||
{tx.executionTxHash ? (
|
{tx.executionTxHash ? (
|
||||||
<a href={getEtherScanLink('tx', tx.executionTxHash)} target="_blank" rel="noopener noreferrer">
|
<EtherScanLink type="tx" value={tx.executionTxHash} cut={8} />
|
||||||
{shortVersionOf(tx.executionTxHash, 4)}
|
|
||||||
<OpenInNew style={openIconStyle} />
|
|
||||||
</a>
|
|
||||||
) : (
|
) : (
|
||||||
'n/a'
|
'n/a'
|
||||||
)}
|
)}
|
||||||
</Paragraph>
|
</Block>
|
||||||
<Paragraph noMargin>
|
<Paragraph noMargin>
|
||||||
<Bold>TX status: </Bold>
|
<Bold>TX status: </Bold>
|
||||||
<Span className={classes[tx.status]} style={{ fontWeight: 'bold' }}>
|
<Span>
|
||||||
{txStatusToLabel[tx.status]}
|
{txStatusToLabel[tx.status]}
|
||||||
</Span>
|
</Span>
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
md, lg, connected, error, disabled,
|
md, lg, connected, error, disabled, border,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
|
expandedTxBlock: {
|
||||||
|
borderBottom: `2px solid ${border}`,
|
||||||
|
},
|
||||||
txDataContainer: {
|
txDataContainer: {
|
||||||
padding: `${lg} ${md}`,
|
padding: `${lg} ${md}`,
|
||||||
},
|
},
|
||||||
|
txData: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
awaiting_your_confirmation: {
|
||||||
|
color: disabled,
|
||||||
|
},
|
||||||
awaiting_confirmations: {
|
awaiting_confirmations: {
|
||||||
color: disabled,
|
color: disabled,
|
||||||
},
|
},
|
||||||
@ -19,4 +29,7 @@ export const styles = () => ({
|
|||||||
cancelled: {
|
cancelled: {
|
||||||
color: error,
|
color: error,
|
||||||
},
|
},
|
||||||
|
txHash: {
|
||||||
|
paddingRight: '3px',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,7 @@ type Props = {
|
|||||||
const statusToIcon = {
|
const statusToIcon = {
|
||||||
success: OkIcon,
|
success: OkIcon,
|
||||||
cancelled: ErrorIcon,
|
cancelled: ErrorIcon,
|
||||||
|
awaiting_your_confirmation: AwaitingIcon,
|
||||||
awaiting_confirmations: AwaitingIcon,
|
awaiting_confirmations: AwaitingIcon,
|
||||||
awaiting_execution: AwaitingIcon,
|
awaiting_execution: AwaitingIcon,
|
||||||
pending: <CircularProgress size={14} />,
|
pending: <CircularProgress size={14} />,
|
||||||
@ -26,9 +27,10 @@ const statusToIcon = {
|
|||||||
|
|
||||||
const statusToLabel = {
|
const statusToLabel = {
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
cancelled: 'Cancelled',
|
cancelled: 'Failed',
|
||||||
awaiting_confirmations: 'Awaiting',
|
awaiting_your_confirmation: 'Awaiting your confirmation',
|
||||||
awaiting_execution: 'Awaiting',
|
awaiting_confirmations: 'Awaiting confirmations',
|
||||||
|
awaiting_execution: 'Awaiting execution',
|
||||||
pending: 'Pending',
|
pending: 'Pending',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ const Status = ({ classes, status }: Props) => {
|
|||||||
{typeof Icon === 'object' ? (
|
{typeof Icon === 'object' ? (
|
||||||
Icon
|
Icon
|
||||||
) : (
|
) : (
|
||||||
<Img src={Icon} alt="OK Icon" style={statusIconStyle} />
|
<Img src={Icon} alt={statusToLabel[status]} style={statusIconStyle} />
|
||||||
)}
|
)}
|
||||||
<Paragraph noMargin className={classes.statusText}>
|
<Paragraph noMargin className={classes.statusText}>
|
||||||
{statusToLabel[status]}
|
{statusToLabel[status]}
|
||||||
|
@ -1,32 +1,40 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
smallFontSize, boldFont, sm, error, disabled, primary,
|
boldFont, sm, lg, error, disabled, extraSmallFontSize, secondary,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
container: {
|
container: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
fontSize: smallFontSize,
|
fontSize: extraSmallFontSize,
|
||||||
fontWeight: boldFont,
|
fontWeight: boldFont,
|
||||||
width: '100px',
|
|
||||||
padding: sm,
|
padding: sm,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
|
height: lg,
|
||||||
|
marginTop: sm,
|
||||||
|
marginBottom: sm,
|
||||||
|
borderRadius: '3px',
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
backgroundColor: '#A1D2CA',
|
backgroundColor: '#A1D2CA',
|
||||||
color: primary,
|
color: secondary,
|
||||||
},
|
},
|
||||||
cancelled: {
|
cancelled: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
color: error,
|
color: error,
|
||||||
|
border: `1px solid ${error}`,
|
||||||
|
},
|
||||||
|
awaiting_your_confirmation: {
|
||||||
|
backgroundColor: '#d4d5d3',
|
||||||
|
color: disabled,
|
||||||
},
|
},
|
||||||
awaiting_confirmations: {
|
awaiting_confirmations: {
|
||||||
backgroundColor: '#dfebff',
|
backgroundColor: '#d4d5d3',
|
||||||
color: disabled,
|
color: disabled,
|
||||||
},
|
},
|
||||||
awaiting_execution: {
|
awaiting_execution: {
|
||||||
backgroundColor: '#dfebff',
|
backgroundColor: '#d4d5d3',
|
||||||
color: disabled,
|
color: disabled,
|
||||||
},
|
},
|
||||||
pending: {
|
pending: {
|
||||||
@ -34,7 +42,6 @@ export const styles = () => ({
|
|||||||
color: '#e8673c',
|
color: '#e8673c',
|
||||||
},
|
},
|
||||||
statusText: {
|
statusText: {
|
||||||
marginLeft: 'auto',
|
padding: '0 7px',
|
||||||
textTransform: 'uppercase',
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="10" viewBox="0 0 14 10">
|
||||||
|
<path fill="#5D6D74" fill-rule="nonzero" d="M2.849 5L6.41 8.571 4.986 10 0 5l4.986-5L6.41 1.429 2.849 5zm8.302 0L7.59 1.429 9.014 0 14 5l-4.986 5L7.59 8.571 11.151 5z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 265 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
|
||||||
|
<path fill="#008C73" fill-rule="nonzero" d="M10 1.007L8.993 0 1.429 7.564V2.857H0V10h7.143V8.571H2.436z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 202 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
|
||||||
|
<path fill="#F02525" fill-rule="nonzero" d="M0 8.993L1.007 10l7.564-7.564v4.707H10V0H2.857v1.429h4.707z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 202 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
||||||
|
<path fill="#5D6D74" fill-rule="nonzero" d="M6.001 8.1C4.81 8.1 3.842 7.16 3.842 6c0-1.16.967-2.1 2.16-2.1 1.192 0 2.158.94 2.158 2.1 0 1.16-.966 2.1-2.159 2.1zm4.583-1.518c.025-.192.044-.384.044-.582 0-.198-.019-.396-.044-.6l1.302-.978a.297.297 0 0 0 .074-.384l-1.234-2.076a.307.307 0 0 0-.376-.132l-1.536.6a4.503 4.503 0 0 0-1.042-.588L7.543.252A.31.31 0 0 0 7.235 0H4.768a.31.31 0 0 0-.309.252l-.228 1.59c-.389.15-.722.354-1.042.588l-1.536-.6a.307.307 0 0 0-.377.132L.043 4.038a.29.29 0 0 0 .074.384l1.301.978a4.993 4.993 0 0 0-.043.6c0 .198.019.39.043.582l-1.301.996a.29.29 0 0 0-.074.384l1.233 2.076c.074.132.241.18.377.132l1.536-.606c.32.24.653.444 1.042.594l.228 1.59a.31.31 0 0 0 .309.252h2.467a.31.31 0 0 0 .308-.252l.229-1.59a4.522 4.522 0 0 0 1.042-.594l1.536.606c.136.048.302 0 .376-.132l1.234-2.076a.297.297 0 0 0-.074-.384l-1.302-.996z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 948 B |
@ -0,0 +1,44 @@
|
|||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import Block from '~/components/layout/Block'
|
||||||
|
import Paragraph from '~/components/layout/Paragraph/'
|
||||||
|
import Img from '~/components/layout/Img'
|
||||||
|
import { type TransactionType } from '~/routes/safe/store/models/transaction'
|
||||||
|
import OutgoingTxIcon from './assets/outgoing.svg'
|
||||||
|
import IncomingTxIcon from './assets/incoming.svg'
|
||||||
|
import CustomTxIcon from './assets/custom.svg'
|
||||||
|
import SettingsTxIcon from './assets/settings.svg'
|
||||||
|
import { styles } from './style'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
classes: Object,
|
||||||
|
txType: TransactionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeToIcon = {
|
||||||
|
outgoing: OutgoingTxIcon,
|
||||||
|
incoming: IncomingTxIcon,
|
||||||
|
custom: CustomTxIcon,
|
||||||
|
settings: SettingsTxIcon,
|
||||||
|
creation: SettingsTxIcon,
|
||||||
|
cancellation: SettingsTxIcon,
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeToLabel = {
|
||||||
|
outgoing: 'Outgoing transfer',
|
||||||
|
incoming: 'Incoming transfer',
|
||||||
|
custom: 'Custom transaction',
|
||||||
|
settings: 'Modify settings',
|
||||||
|
creation: 'Safe created',
|
||||||
|
cancellation: 'Cancellation transaction',
|
||||||
|
}
|
||||||
|
|
||||||
|
const TxType = ({ classes, txType }: Props) => (
|
||||||
|
<Block className={classes.container}>
|
||||||
|
<Img src={typeToIcon[txType]} alt={typeToLabel[txType]} className={classes.img} />
|
||||||
|
<Paragraph className={classes.type} noMargin>{typeToLabel[txType]}</Paragraph>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withStyles(styles)(TxType)
|
@ -0,0 +1,12 @@
|
|||||||
|
// @flow
|
||||||
|
export const styles = () => ({
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
},
|
||||||
|
img: {
|
||||||
|
marginRight: '5px',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
height: '17px',
|
||||||
|
},
|
||||||
|
})
|
@ -1,7 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import React from 'react'
|
||||||
import { format, getTime, parseISO } from 'date-fns'
|
import { format, getTime, parseISO } from 'date-fns'
|
||||||
import { BigNumber } from 'bignumber.js'
|
import { BigNumber } from 'bignumber.js'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
|
import TxType from './TxType'
|
||||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||||
import { type SortRow, buildOrderFieldFrom } from '~/components/Table/sorting'
|
import { type SortRow, buildOrderFieldFrom } from '~/components/Table/sorting'
|
||||||
import { type Column } from '~/components/Table/TableHead'
|
import { type Column } from '~/components/Table/TableHead'
|
||||||
@ -17,7 +19,7 @@ export const TX_TABLE_EXPAND_ICON = 'expand'
|
|||||||
|
|
||||||
type TxData = {
|
type TxData = {
|
||||||
nonce: number,
|
nonce: number,
|
||||||
type: string,
|
type: React.ReactNode,
|
||||||
date: string,
|
date: string,
|
||||||
amount: number | string,
|
amount: number | string,
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
@ -47,20 +49,31 @@ export type TransactionRow = SortRow<TxData>
|
|||||||
export const getTxTableData = (transactions: List<Transaction>): List<TransactionRow> => {
|
export const getTxTableData = (transactions: List<Transaction>): List<TransactionRow> => {
|
||||||
const rows = transactions.map((tx: Transaction) => {
|
const rows = transactions.map((tx: Transaction) => {
|
||||||
const txDate = tx.isExecuted ? tx.executionDate : tx.submissionDate
|
const txDate = tx.isExecuted ? tx.executionDate : tx.submissionDate
|
||||||
let txType = 'Outgoing transfer'
|
let txType = 'outgoing'
|
||||||
if (tx.modifySettingsTx) {
|
if (tx.modifySettingsTx) {
|
||||||
txType = 'Modify Safe Settings'
|
txType = 'settings'
|
||||||
} else if (tx.cancellationTx) {
|
} else if (tx.cancellationTx) {
|
||||||
txType = 'Cancellation transaction'
|
txType = 'cancellation'
|
||||||
} else if (tx.customTx) {
|
} else if (tx.customTx) {
|
||||||
txType = 'Custom transaction'
|
txType = 'custom'
|
||||||
|
} else if (tx.creationTx) {
|
||||||
|
txType = 'creation'
|
||||||
|
}
|
||||||
|
|
||||||
|
let txIndex = 1
|
||||||
|
if (tx.nonce) {
|
||||||
|
txIndex = tx.nonce + 2
|
||||||
|
} else if (tx.nonce === 0) {
|
||||||
|
txIndex = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[TX_TABLE_NONCE_ID]: tx.nonce,
|
[TX_TABLE_NONCE_ID]: txIndex,
|
||||||
[TX_TABLE_TYPE_ID]: txType,
|
[TX_TABLE_TYPE_ID]: <TxType txType={txType} />,
|
||||||
[TX_TABLE_DATE_ID]: formatDate(tx.isExecuted ? tx.executionDate : tx.submissionDate),
|
[TX_TABLE_DATE_ID]: tx.isExecuted
|
||||||
[buildOrderFieldFrom(TX_TABLE_DATE_ID)]: getTime(parseISO(txDate)),
|
? tx.executionDate && formatDate(tx.executionDate)
|
||||||
|
: tx.submissionDate && formatDate(tx.submissionDate),
|
||||||
|
[buildOrderFieldFrom(TX_TABLE_DATE_ID)]: txDate ? getTime(parseISO(txDate)) : null,
|
||||||
[TX_TABLE_AMOUNT_ID]: getTxAmount(tx),
|
[TX_TABLE_AMOUNT_ID]: getTxAmount(tx),
|
||||||
[TX_TABLE_STATUS_ID]: tx.status,
|
[TX_TABLE_STATUS_ID]: tx.status,
|
||||||
[TX_TABLE_RAW_TX_ID]: tx,
|
[TX_TABLE_RAW_TX_ID]: tx,
|
||||||
@ -74,7 +87,7 @@ export const generateColumns = () => {
|
|||||||
const nonceColumn: Column = {
|
const nonceColumn: Column = {
|
||||||
id: TX_TABLE_NONCE_ID,
|
id: TX_TABLE_NONCE_ID,
|
||||||
disablePadding: false,
|
disablePadding: false,
|
||||||
label: 'Nonce',
|
label: 'Id',
|
||||||
custom: false,
|
custom: false,
|
||||||
order: false,
|
order: false,
|
||||||
width: 50,
|
width: 50,
|
||||||
@ -95,7 +108,7 @@ export const generateColumns = () => {
|
|||||||
disablePadding: false,
|
disablePadding: false,
|
||||||
label: 'Amount',
|
label: 'Amount',
|
||||||
custom: false,
|
custom: false,
|
||||||
width: 100,
|
width: 120,
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateColumn: Column = {
|
const dateColumn: Column = {
|
||||||
@ -112,6 +125,7 @@ export const generateColumns = () => {
|
|||||||
disablePadding: false,
|
disablePadding: false,
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
custom: true,
|
custom: true,
|
||||||
|
align: 'right',
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandIconColumn: Column = {
|
const expandIconColumn: Column = {
|
||||||
|
@ -26,7 +26,7 @@ export const TRANSACTION_ROW_TEST_ID = 'transaction-row'
|
|||||||
|
|
||||||
const expandCellStyle = {
|
const expandCellStyle = {
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
paddingRight: 0,
|
paddingRight: 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -68,6 +68,7 @@ const TxsTable = ({
|
|||||||
label="Transactions"
|
label="Transactions"
|
||||||
defaultOrderBy={TX_TABLE_DATE_ID}
|
defaultOrderBy={TX_TABLE_DATE_ID}
|
||||||
defaultOrder="desc"
|
defaultOrder="desc"
|
||||||
|
defaultRowsPerPage={25}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={filteredData}
|
data={filteredData}
|
||||||
size={filteredData.size}
|
size={filteredData.size}
|
||||||
@ -84,7 +85,7 @@ const TxsTable = ({
|
|||||||
{autoColumns.map((column: Column) => (
|
{autoColumns.map((column: Column) => (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={column.id}
|
key={column.id}
|
||||||
className={classes.cell}
|
className={cn(classes.cell, row.status === 'cancelled' && classes.cancelledRow)}
|
||||||
style={cellWidth(column.width)}
|
style={cellWidth(column.width)}
|
||||||
align={column.align}
|
align={column.align}
|
||||||
component="td"
|
component="td"
|
||||||
@ -98,31 +99,37 @@ const TxsTable = ({
|
|||||||
</Row>
|
</Row>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell style={expandCellStyle}>
|
<TableCell style={expandCellStyle}>
|
||||||
<IconButton disableRipple>{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}</IconButton>
|
{!row.tx.creationTx && (
|
||||||
</TableCell>
|
<IconButton disableRipple>
|
||||||
</TableRow>
|
{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}
|
||||||
<TableRow>
|
</IconButton>
|
||||||
<TableCell
|
)}
|
||||||
style={{ paddingBottom: 0, paddingTop: 0 }}
|
|
||||||
colSpan={6}
|
|
||||||
className={classes.extendedTxContainer}
|
|
||||||
>
|
|
||||||
<Collapse
|
|
||||||
in={expandedTx === row.tx.safeTxHash}
|
|
||||||
timeout="auto"
|
|
||||||
component={ExpandedTxComponent}
|
|
||||||
unmountOnExit
|
|
||||||
tx={row[TX_TABLE_RAW_TX_ID]}
|
|
||||||
threshold={threshold}
|
|
||||||
owners={owners}
|
|
||||||
granted={granted}
|
|
||||||
userAddress={userAddress}
|
|
||||||
createTransaction={createTransaction}
|
|
||||||
processTransaction={processTransaction}
|
|
||||||
safeAddress={safeAddress}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
{!row.tx.creationTx && (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
style={{ paddingBottom: 0, paddingTop: 0 }}
|
||||||
|
colSpan={6}
|
||||||
|
className={classes.extendedTxContainer}
|
||||||
|
>
|
||||||
|
<Collapse
|
||||||
|
in={expandedTx === row.tx.safeTxHash}
|
||||||
|
timeout="auto"
|
||||||
|
component={ExpandedTxComponent}
|
||||||
|
unmountOnExit
|
||||||
|
tx={row[TX_TABLE_RAW_TX_ID]}
|
||||||
|
threshold={threshold}
|
||||||
|
owners={owners}
|
||||||
|
granted={granted}
|
||||||
|
userAddress={userAddress}
|
||||||
|
createTransaction={createTransaction}
|
||||||
|
processTransaction={processTransaction}
|
||||||
|
safeAddress={safeAddress}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</Table>
|
</Table>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { lg } from '~/theme/variables'
|
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
container: {
|
container: {
|
||||||
marginTop: lg,
|
marginTop: '70px',
|
||||||
},
|
},
|
||||||
row: {
|
row: {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@ -14,11 +12,19 @@ export const styles = () => ({
|
|||||||
expandedRow: {
|
expandedRow: {
|
||||||
backgroundColor: '#fff3e2',
|
backgroundColor: '#fff3e2',
|
||||||
},
|
},
|
||||||
|
cancelledRow: {
|
||||||
|
opacity: 0.4,
|
||||||
|
},
|
||||||
extendedTxContainer: {
|
extendedTxContainer: {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
|
border: 0,
|
||||||
'&:last-child': {
|
'&:last-child': {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
},
|
},
|
||||||
backgroundColor: '#fffaf4',
|
backgroundColor: '#fffaf4',
|
||||||
},
|
},
|
||||||
|
actions: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import NoTransactions from '~/routes/safe/components/Transactions/NoTransactions'
|
|
||||||
import TxsTable from '~/routes/safe/components/Transactions/TxsTable'
|
import TxsTable from '~/routes/safe/components/Transactions/TxsTable'
|
||||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||||
@ -19,6 +18,8 @@ type Props = {
|
|||||||
currentNetwork: string,
|
currentNetwork: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000
|
||||||
|
|
||||||
const Transactions = ({
|
const Transactions = ({
|
||||||
transactions = List(),
|
transactions = List(),
|
||||||
owners,
|
owners,
|
||||||
@ -31,30 +32,30 @@ const Transactions = ({
|
|||||||
fetchTransactions,
|
fetchTransactions,
|
||||||
currentNetwork,
|
currentNetwork,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
let intervalId: IntervalID
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTransactions(safeAddress)
|
fetchTransactions(safeAddress)
|
||||||
|
|
||||||
|
intervalId = setInterval(() => {
|
||||||
|
fetchTransactions(safeAddress)
|
||||||
|
}, TIMEOUT)
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId)
|
||||||
}, [safeAddress])
|
}, [safeAddress])
|
||||||
|
|
||||||
const hasTransactions = transactions.size > 0
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<TxsTable
|
||||||
{hasTransactions ? (
|
transactions={transactions}
|
||||||
<TxsTable
|
threshold={threshold}
|
||||||
transactions={transactions}
|
owners={owners}
|
||||||
threshold={threshold}
|
userAddress={userAddress}
|
||||||
owners={owners}
|
currentNetwork={currentNetwork}
|
||||||
userAddress={userAddress}
|
granted={granted}
|
||||||
currentNetwork={currentNetwork}
|
safeAddress={safeAddress}
|
||||||
granted={granted}
|
createTransaction={createTransaction}
|
||||||
safeAddress={safeAddress}
|
processTransaction={processTransaction}
|
||||||
createTransaction={createTransaction}
|
/>
|
||||||
processTransaction={processTransaction}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<NoTransactions />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,17 +33,22 @@ export type SelectorProps = {
|
|||||||
transactions: List<Transaction>,
|
transactions: List<Transaction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTxStatus = (tx: Transaction, safe: Safe): TransactionStatus => {
|
const getTxStatus = (tx: Transaction, userAddress: string, safe: Safe): TransactionStatus => {
|
||||||
let txStatus = 'awaiting_confirmations'
|
let txStatus
|
||||||
|
|
||||||
if (tx.executionTxHash) {
|
if (tx.executionTxHash) {
|
||||||
txStatus = 'success'
|
txStatus = 'success'
|
||||||
} else if (tx.cancelled) {
|
} else if (tx.cancelled) {
|
||||||
txStatus = 'cancelled'
|
txStatus = 'cancelled'
|
||||||
} else if (tx.confirmations.size === safe.threshold) {
|
} else if (tx.confirmations.size === safe.threshold) {
|
||||||
txStatus = 'awaiting_execution'
|
txStatus = 'awaiting_execution'
|
||||||
|
} else if (tx.creationTx) {
|
||||||
|
txStatus = 'success'
|
||||||
} else if (!tx.confirmations.size) {
|
} else if (!tx.confirmations.size) {
|
||||||
txStatus = 'pending'
|
txStatus = 'pending'
|
||||||
|
} else {
|
||||||
|
const userConfirmed = tx.confirmations.filter((conf) => conf.owner.address === userAddress).size === 1
|
||||||
|
const userIsSafeOwner = safe.owners.filter((owner) => owner.address === userAddress).size === 1
|
||||||
|
txStatus = !userConfirmed && userIsSafeOwner ? 'awaiting_your_confirmation' : 'awaiting_confirmations'
|
||||||
}
|
}
|
||||||
|
|
||||||
return txStatus
|
return txStatus
|
||||||
@ -108,8 +113,9 @@ const extendedSafeTokensSelector: Selector<GlobalState, RouterProps, List<Token>
|
|||||||
|
|
||||||
const extendedTransactionsSelector: Selector<GlobalState, RouterProps, List<Transaction>> = createSelector(
|
const extendedTransactionsSelector: Selector<GlobalState, RouterProps, List<Transaction>> = createSelector(
|
||||||
safeSelector,
|
safeSelector,
|
||||||
|
userAccountSelector,
|
||||||
safeTransactionsSelector,
|
safeTransactionsSelector,
|
||||||
(safe, transactions) => {
|
(safe, userAddress, transactions) => {
|
||||||
const extendedTransactions = transactions.map((tx: Transaction) => {
|
const extendedTransactions = transactions.map((tx: Transaction) => {
|
||||||
let extendedTx = tx
|
let extendedTx = tx
|
||||||
|
|
||||||
@ -117,15 +123,17 @@ const extendedTransactionsSelector: Selector<GlobalState, RouterProps, List<Tran
|
|||||||
// it means that the transaction was cancelled (Replaced) and shouldn't get executed
|
// it means that the transaction was cancelled (Replaced) and shouldn't get executed
|
||||||
let replacementTransaction
|
let replacementTransaction
|
||||||
if (!tx.isExecuted) {
|
if (!tx.isExecuted) {
|
||||||
replacementTransaction = transactions.findLast(
|
replacementTransaction = transactions.size > 1 && transactions.findLast(
|
||||||
(transaction) => transaction.isExecuted && transaction.nonce >= tx.nonce,
|
(transaction) => (
|
||||||
|
transaction.isExecuted && transaction.nonce && transaction.nonce >= tx.nonce
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if (replacementTransaction) {
|
if (replacementTransaction) {
|
||||||
extendedTx = tx.set('cancelled', true)
|
extendedTx = tx.set('cancelled', true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return extendedTx.set('status', getTxStatus(extendedTx, safe))
|
return extendedTx.set('status', getTxStatus(extendedTx, userAddress, safe))
|
||||||
})
|
})
|
||||||
|
|
||||||
return extendedTransactions
|
return extendedTransactions
|
||||||
|
@ -40,6 +40,7 @@ type TxServiceModel = {
|
|||||||
refundReceiver: string,
|
refundReceiver: string,
|
||||||
safeTxHash: string,
|
safeTxHash: string,
|
||||||
submissionDate: string,
|
submissionDate: string,
|
||||||
|
executor: string,
|
||||||
executionDate: string,
|
executionDate: string,
|
||||||
confirmations: ConfirmationServiceModel[],
|
confirmations: ConfirmationServiceModel[],
|
||||||
isExecuted: boolean,
|
isExecuted: boolean,
|
||||||
@ -139,6 +140,7 @@ export const buildTransactionFrom = async (
|
|||||||
refundParams,
|
refundParams,
|
||||||
isExecuted: tx.isExecuted,
|
isExecuted: tx.isExecuted,
|
||||||
submissionDate: tx.submissionDate,
|
submissionDate: tx.submissionDate,
|
||||||
|
executor: tx.executor,
|
||||||
executionDate: tx.executionDate,
|
executionDate: tx.executionDate,
|
||||||
executionTxHash: tx.transactionHash,
|
executionTxHash: tx.transactionHash,
|
||||||
safeTxHash: tx.safeTxHash,
|
safeTxHash: tx.safeTxHash,
|
||||||
@ -147,29 +149,54 @@ export const buildTransactionFrom = async (
|
|||||||
modifySettingsTx,
|
modifySettingsTx,
|
||||||
customTx,
|
customTx,
|
||||||
cancellationTx,
|
cancellationTx,
|
||||||
|
creationTx: tx.creationTx,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addMockSafeCreationTx = (safeAddress) => [{
|
||||||
|
baseGas: 0,
|
||||||
|
confirmations: [],
|
||||||
|
data: null,
|
||||||
|
executionDate: null,
|
||||||
|
gasPrice: 0,
|
||||||
|
gasToken: '0x0000000000000000000000000000000000000000',
|
||||||
|
isExecuted: true,
|
||||||
|
nonce: null,
|
||||||
|
operation: 0,
|
||||||
|
refundReceiver: '0x0000000000000000000000000000000000000000',
|
||||||
|
safe: safeAddress,
|
||||||
|
safeTxGas: 0,
|
||||||
|
safeTxHash: '',
|
||||||
|
signatures: null,
|
||||||
|
submissionDate: null,
|
||||||
|
executor: '',
|
||||||
|
to: '',
|
||||||
|
transactionHash: null,
|
||||||
|
value: 0,
|
||||||
|
creationTx: true,
|
||||||
|
}]
|
||||||
|
|
||||||
export const loadSafeTransactions = async (safeAddress: string) => {
|
export const loadSafeTransactions = async (safeAddress: string) => {
|
||||||
web3 = await getWeb3()
|
web3 = await getWeb3()
|
||||||
|
|
||||||
const url = buildTxServiceUrl(safeAddress)
|
let transactions: TxServiceModel[] = addMockSafeCreationTx(safeAddress)
|
||||||
const response = await axios.get(url)
|
try {
|
||||||
const transactions: TxServiceModel[] = response.data.results
|
const url = buildTxServiceUrl(safeAddress)
|
||||||
|
const response = await axios.get(url)
|
||||||
|
if (response.data.count > 0) {
|
||||||
|
transactions = transactions.concat(response.data.results)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Requests for transactions for ${safeAddress} failed with 404`, err)
|
||||||
|
}
|
||||||
const safeSubjects = loadSafeSubjects(safeAddress)
|
const safeSubjects = loadSafeSubjects(safeAddress)
|
||||||
const txsRecord = await Promise.all(
|
const txsRecord = await Promise.all(
|
||||||
transactions.map((tx: TxServiceModel) => buildTransactionFrom(safeAddress, tx, safeSubjects)),
|
transactions.map((tx: TxServiceModel) => buildTransactionFrom(safeAddress, tx, safeSubjects)),
|
||||||
)
|
)
|
||||||
|
|
||||||
return Map().set(safeAddress, List(txsRecord))
|
return Map().set(safeAddress, List(txsRecord))
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
try {
|
const transactions: Map<string, List<Transaction>> = await loadSafeTransactions(safeAddress)
|
||||||
const transactions: Map<string, List<Transaction>> = await loadSafeTransactions(safeAddress)
|
return dispatch(addTransactions(transactions))
|
||||||
|
|
||||||
return dispatch(addTransactions(transactions))
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Requests for transactions for ${safeAddress} failed with 404`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -124,8 +124,8 @@ const safeStorageMware = (store: Store<GlobalState>) => (next: Function) => asyn
|
|||||||
case SET_DEFAULT_SAFE: {
|
case SET_DEFAULT_SAFE: {
|
||||||
if (action.payload) {
|
if (action.payload) {
|
||||||
saveDefaultSafe(action.payload)
|
saveDefaultSafe(action.payload)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
@ -4,7 +4,15 @@ import type { RecordFactory, RecordOf } from 'immutable'
|
|||||||
import { type Confirmation } from '~/routes/safe/store/models/confirmation'
|
import { type Confirmation } from '~/routes/safe/store/models/confirmation'
|
||||||
import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses'
|
import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses'
|
||||||
|
|
||||||
export type TransactionStatus = 'awaiting_confirmations' | 'success' | 'cancelled' | 'awaiting_execution' | 'pending'
|
export type TransactionType = 'incoming' | 'outgoing' | 'settings' | 'custom' | 'creation' | 'cancellation'
|
||||||
|
|
||||||
|
export type TransactionStatus =
|
||||||
|
| 'awaiting_your_confirmation'
|
||||||
|
| 'awaiting_confirmations'
|
||||||
|
| 'success'
|
||||||
|
| 'cancelled'
|
||||||
|
| 'awaiting_execution'
|
||||||
|
| 'pending'
|
||||||
|
|
||||||
export type TransactionProps = {
|
export type TransactionProps = {
|
||||||
nonce: number,
|
nonce: number,
|
||||||
@ -25,7 +33,9 @@ export type TransactionProps = {
|
|||||||
modifySettingsTx: boolean,
|
modifySettingsTx: boolean,
|
||||||
cancellationTx: boolean,
|
cancellationTx: boolean,
|
||||||
customTx: boolean,
|
customTx: boolean,
|
||||||
|
creationTx: boolean,
|
||||||
safeTxHash: string,
|
safeTxHash: string,
|
||||||
|
executor: string,
|
||||||
executionTxHash?: string,
|
executionTxHash?: string,
|
||||||
decimals?: number,
|
decimals?: number,
|
||||||
cancelled?: boolean,
|
cancelled?: boolean,
|
||||||
@ -49,6 +59,7 @@ export const makeTransaction: RecordFactory<TransactionProps> = Record({
|
|||||||
refundReceiver: ZERO_ADDRESS,
|
refundReceiver: ZERO_ADDRESS,
|
||||||
isExecuted: false,
|
isExecuted: false,
|
||||||
submissionDate: '',
|
submissionDate: '',
|
||||||
|
executor: '',
|
||||||
executionDate: '',
|
executionDate: '',
|
||||||
symbol: '',
|
symbol: '',
|
||||||
executionTxHash: undefined,
|
executionTxHash: undefined,
|
||||||
@ -57,6 +68,7 @@ export const makeTransaction: RecordFactory<TransactionProps> = Record({
|
|||||||
modifySettingsTx: false,
|
modifySettingsTx: false,
|
||||||
cancellationTx: false,
|
cancellationTx: false,
|
||||||
customTx: false,
|
customTx: false,
|
||||||
|
creationTx: false,
|
||||||
status: 'awaiting',
|
status: 'awaiting',
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
isTokenTransfer: false,
|
isTokenTransfer: false,
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { select } from '@storybook/addon-knobs'
|
|
||||||
import { storiesOf } from '@storybook/react'
|
|
||||||
import * as React from 'react'
|
|
||||||
import styles from '~/components/layout/PageFrame/index.scss'
|
|
||||||
import Component from './Layout'
|
|
||||||
|
|
||||||
const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
|
||||||
|
|
||||||
storiesOf('Routes /welcome', module)
|
|
||||||
.addDecorator(FrameDecorator)
|
|
||||||
.add('Welcome with Gnosis Safe connected', () => {
|
|
||||||
const provider = select('Status by Provider', ['', 'UNKNOWN', 'SAFE', 'METAMASK', 'PARITY'], 'SAFE')
|
|
||||||
return <Component provider={provider} fetchProvider={() => {}} />
|
|
||||||
})
|
|
||||||
.add('Welcome with Metamask connected', () => {
|
|
||||||
const provider = select('Status by Provider', ['', 'UNKNOWN', 'SAFE', 'METAMASK', 'PARITY'], 'METAMASK')
|
|
||||||
return <Component provider={provider} fetchProvider={() => {}} />
|
|
||||||
})
|
|
||||||
.add('Welcome with unknown wallet', () => {
|
|
||||||
const provider = select('Status by Provider', ['', 'UNKNOWN', 'SAFE', 'METAMASK', 'PARITY'], 'UNKNOWN')
|
|
||||||
return <Component provider={provider} fetchProvider={() => {}} />
|
|
||||||
})
|
|
||||||
.add('Welcome without wallet connected', () => {
|
|
||||||
const provider = select('Status by Provider', ['', 'UNKNOWN', 'SAFE', 'METAMASK', 'PARITY'], '')
|
|
||||||
return <Component provider={provider} fetchProvider={() => {}} />
|
|
||||||
})
|
|
@ -63,7 +63,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
color: disabled,
|
color: disabled,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
borderRadius: '8px',
|
borderRadius: sm,
|
||||||
},
|
},
|
||||||
contained: {
|
contained: {
|
||||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||||
@ -102,7 +102,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiStepper: {
|
MuiStepper: {
|
||||||
root: {
|
root: {
|
||||||
padding: '24px 0 0 15px',
|
padding: `${lg} 0 0 15px`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiIconButton: {
|
MuiIconButton: {
|
||||||
@ -238,6 +238,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiTablePagination: {
|
MuiTablePagination: {
|
||||||
toolbar: {
|
toolbar: {
|
||||||
|
paddingRight: '15px',
|
||||||
'& > span:nth-child(2)': {
|
'& > span:nth-child(2)': {
|
||||||
order: 1,
|
order: 1,
|
||||||
},
|
},
|
||||||
@ -255,11 +256,11 @@ export default createMuiTheme({
|
|||||||
input: {
|
input: {
|
||||||
order: 2,
|
order: 2,
|
||||||
width: '60px',
|
width: '60px',
|
||||||
padding: `0 ${md} 0 0`,
|
color: disabled,
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
paddingRight: 30,
|
paddingRight: 30,
|
||||||
minWidth: '20px',
|
minWidth: lg,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
order: 4,
|
order: 4,
|
||||||
@ -270,6 +271,9 @@ export default createMuiTheme({
|
|||||||
root: {
|
root: {
|
||||||
fontSize: extraSmallFontSize,
|
fontSize: extraSmallFontSize,
|
||||||
},
|
},
|
||||||
|
active: {
|
||||||
|
fontWeight: boldFont,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
MuiTableCell: {
|
MuiTableCell: {
|
||||||
root: {
|
root: {
|
||||||
@ -280,7 +284,6 @@ export default createMuiTheme({
|
|||||||
head: {
|
head: {
|
||||||
letterSpacing: '1px',
|
letterSpacing: '1px',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
fontWeight: boldFont,
|
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
color: primary,
|
color: primary,
|
||||||
|