* 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,6 +1,5 @@
|
|||
node_modules/
|
||||
build_webpack/
|
||||
build_storybook/
|
||||
.DS_Store
|
||||
build/
|
||||
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',
|
||||
options: {
|
||||
esModule: false,
|
||||
name: 'img/[hash].[ext]',
|
||||
esModule: false
|
||||
},
|
||||
|
|
|
@ -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'>;
|
||||
}
|
|
@ -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'>;
|
||||
}
|
|
@ -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'>;
|
||||
}
|
|
@ -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'>;
|
||||
}
|
|
@ -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>;
|
||||
}
|
|
@ -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'>;
|
||||
}
|
|
@ -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": {
|
||||
"build": "node scripts/build.js",
|
||||
"build-mainnet": "REACT_APP_NETWORK=mainnet yarn build",
|
||||
"build-storybook": "build-storybook -o build_storybook",
|
||||
"flow": "flow",
|
||||
"precommit": "./precommit.sh",
|
||||
"start": "node scripts/start.js",
|
||||
"start-mainnet": "REACT_APP_NETWORK=mainnet yarn start",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
||||
"format": "prettier-eslint \"src/**/*.js\" --write"
|
||||
},
|
||||
|
@ -44,6 +42,7 @@
|
|||
"bignumber.js": "9.0.0",
|
||||
"connected-react-router": "6.6.1",
|
||||
"date-fns": "2.8.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"ethereum-ens": "0.7.8",
|
||||
"final-form": "4.18.6",
|
||||
"history": "4.10.1",
|
||||
|
@ -56,6 +55,7 @@
|
|||
"polished": "^3.4.2",
|
||||
"qrcode.react": "1.0.0",
|
||||
"react": "16.12.0",
|
||||
"react-dev-utils": "^10.0.0",
|
||||
"react-dom": "16.12.0",
|
||||
"react-final-form": "6.3.3",
|
||||
"react-final-form-listeners": "^1.0.2",
|
||||
|
@ -70,10 +70,9 @@
|
|||
"redux-actions": "^2.6.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"reselect": "^4.0.0",
|
||||
"squarelink": "^1.1.3",
|
||||
"squarelink": "^1.1.4",
|
||||
"web3": "1.2.4",
|
||||
"web3connect": "^1.0.0-beta.23",
|
||||
"react-ga": "^2.7.0"
|
||||
"web3connect": "^1.0.0-beta.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.7.5",
|
||||
|
@ -100,11 +99,6 @@
|
|||
"@babel/preset-env": "7.7.6",
|
||||
"@babel/preset-flow": "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",
|
||||
"autoprefixer": "9.7.3",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
|
@ -118,7 +112,7 @@
|
|||
"classnames": "^2.2.6",
|
||||
"css-loader": "3.2.1",
|
||||
"detect-port": "^1.3.0",
|
||||
"eslint": "5.16.0",
|
||||
"eslint": "6.7.2",
|
||||
"eslint-config-airbnb": "18.0.1",
|
||||
"eslint-plugin-flowtype": "4.5.2",
|
||||
"eslint-plugin-import": "2.19.1",
|
||||
|
@ -142,8 +136,6 @@
|
|||
"pre-commit": "^1.2.2",
|
||||
"prettier-eslint-cli": "5.0.0",
|
||||
"run-with-testrpc": "0.3.1",
|
||||
"storybook-host": "5.1.0",
|
||||
"storybook-router": "^0.3.4",
|
||||
"style-loader": "1.0.1",
|
||||
"terser-webpack-plugin": "^2.2.2",
|
||||
"truffle": "5.1.3",
|
||||
|
|
|
@ -57,6 +57,8 @@ git clone https://github.com/gnosis/safe-transaction-service.git
|
|||
cd safe-transaction-history
|
||||
git checkout develop
|
||||
docker-compose build
|
||||
# it comes enabled by default in docker-compose
|
||||
sudo service postgresql stop
|
||||
docker-compose up -d
|
||||
```
|
||||
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 Link from '~/components/layout/Link'
|
||||
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 { COOKIES_KEY } from '~/logic/cookies/model/cookie'
|
||||
import { loadFromCookie, saveCookie } from '~/logic/cookies/utils'
|
||||
|
@ -38,7 +38,7 @@ const useStyles = makeStyles({
|
|||
text: {
|
||||
color: primary,
|
||||
fontFamily: mainFontFamily,
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
fontWeight: 'normal',
|
||||
lineHeight: '1.38',
|
||||
margin: '0 0 25px',
|
||||
|
|
|
@ -13,14 +13,14 @@ const useStyles = makeStyles({
|
|||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
padding: xs,
|
||||
margin: `0 ${xs}`,
|
||||
borderRadius: '50%',
|
||||
transition: 'background-color .2s ease-in-out',
|
||||
'&:hover': {
|
||||
backgroundColor: '#F0EFEE',
|
||||
},
|
||||
},
|
||||
inreasedPopperZindex: {
|
||||
increasedPopperZindex: {
|
||||
zIndex: 2001,
|
||||
},
|
||||
})
|
||||
|
@ -33,7 +33,7 @@ type CopyBtnProps = {
|
|||
const CopyBtn = ({ content, increaseZindex = false }: CopyBtnProps) => {
|
||||
const [clicked, setClicked] = useState<boolean>(false)
|
||||
const classes = useStyles()
|
||||
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
||||
const customClasses = increaseZindex ? { popper: classes.increasedPopperZindex } : {}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
|
|
|
@ -12,14 +12,14 @@ const useStyles = makeStyles({
|
|||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: xs,
|
||||
margin: `0 ${xs}`,
|
||||
borderRadius: '50%',
|
||||
transition: 'background-color .2s ease-in-out',
|
||||
'&:hover': {
|
||||
backgroundColor: '#F0EFEE',
|
||||
},
|
||||
},
|
||||
inreasedPopperZindex: {
|
||||
increasedPopperZindex: {
|
||||
zIndex: 2001,
|
||||
},
|
||||
})
|
||||
|
@ -32,7 +32,7 @@ type EtherscanBtnProps = {
|
|||
|
||||
const EtherscanBtn = ({ type, value, increaseZindex = false }: EtherscanBtnProps) => {
|
||||
const classes = useStyles()
|
||||
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
||||
const customClasses = increaseZindex ? { popper: classes.increasedPopperZindex } : {}
|
||||
|
||||
return (
|
||||
<Tooltip title="Show details on Etherscan" placement="top" classes={customClasses}>
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
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 { secondary } from '~/theme/variables'
|
||||
|
||||
const openIconStyle = {
|
||||
height: '13px',
|
||||
color: secondary,
|
||||
}
|
||||
import { styles } from './style.js'
|
||||
|
||||
type EtherscanLinkProps = {
|
||||
type: 'tx' | 'address',
|
||||
value: string,
|
||||
cut?: number,
|
||||
classes: Object,
|
||||
}
|
||||
|
||||
const EtherscanLink = ({ type, value }: EtherscanLinkProps) => (
|
||||
<a href={getEtherScanLink(type, value)} target="_blank" rel="noopener noreferrer">
|
||||
{shortVersionOf(value, 4)}
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</a>
|
||||
const EtherscanLink = ({
|
||||
type, value, cut, classes,
|
||||
}: EtherscanLinkProps) => (
|
||||
<Block className={classes.etherscanLink}>
|
||||
<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)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// @flow
|
||||
|
||||
export const styles = () => ({
|
||||
etherscanLink: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
})
|
|
@ -33,7 +33,7 @@ const styles = () => ({
|
|||
padding: 0,
|
||||
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
|
||||
minWidth: '280px',
|
||||
borderRadius: '8px',
|
||||
borderRadius: sm,
|
||||
marginTop: '11px',
|
||||
},
|
||||
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 Modal from '@material-ui/core/Modal'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { sm } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
|
@ -27,7 +28,7 @@ const styles = () => ({
|
|||
top: '120px',
|
||||
width: '500px',
|
||||
height: '530px',
|
||||
borderRadius: '8px',
|
||||
borderRadius: sm,
|
||||
backgroundColor: '#ffffff',
|
||||
boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)',
|
||||
'&:focus': {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { List } from 'immutable'
|
||||
import Table from '@material-ui/core/Table'
|
||||
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 { type Order, stableSort, getSorting } from '~/components/Table/sorting'
|
||||
import TableHead, { type Column } from '~/components/Table/TableHead'
|
||||
import { xl } from '~/theme/variables'
|
||||
import { xxl, xl, sm } from '~/theme/variables'
|
||||
|
||||
type Props<K> = {
|
||||
label: string,
|
||||
|
@ -39,11 +38,12 @@ type State = {
|
|||
const styles = {
|
||||
root: {
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '8px',
|
||||
borderTopRightRadius: sm,
|
||||
borderTopLeftRadius: sm,
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
selectRoot: {
|
||||
lineHeight: '40px',
|
||||
lineHeight: xxl,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
white: {
|
||||
|
@ -53,14 +53,11 @@ const styles = {
|
|||
backgroundColor: 'white',
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
marginBottom: xl,
|
||||
borderRadius: '8px',
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: sm,
|
||||
borderBottomLeftRadius: sm,
|
||||
},
|
||||
loader: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'white',
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -125,6 +122,13 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
|||
|
||||
getEmptyStyle = (emptyRows: number) => ({
|
||||
height: FIXED_HEIGHT * emptyRows,
|
||||
borderTopRightRadius: sm,
|
||||
borderTopLeftRadius: sm,
|
||||
backgroundColor: 'white',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
const emptyRows = displayRows - Math.min(displayRows, data.length - page * displayRows)
|
||||
const emptyRows = displayRows - Math.min(displayRows, data.size - page * displayRows)
|
||||
const isEmpty = size === 0
|
||||
|
||||
return (
|
||||
|
@ -184,7 +188,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
|||
)}
|
||||
{isEmpty && (
|
||||
<Row
|
||||
className={classNames(classes.loader, !noBorder && classes.root)}
|
||||
className={classes.loader}
|
||||
style={this.getEmptyStyle(emptyRows + 1)}
|
||||
>
|
||||
<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 CookiesBanner from '~/components/CookiesBanner'
|
||||
import styles from './index.scss'
|
||||
import { fontColor } from '~/theme/variables'
|
||||
|
||||
const notificationStyles = {
|
||||
success: {
|
||||
|
@ -24,7 +25,7 @@ const notificationStyles = {
|
|||
fontFamily: 'Averta',
|
||||
fontSize: '14px',
|
||||
lineHeight: 1.43,
|
||||
color: '#001428',
|
||||
color: fontColor,
|
||||
minHeight: '58px',
|
||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
|
@ -33,7 +34,7 @@ const notificationStyles = {
|
|||
fontFamily: 'Averta',
|
||||
fontSize: '14px',
|
||||
lineHeight: 1.43,
|
||||
color: '#001428',
|
||||
color: fontColor,
|
||||
minHeight: '58px',
|
||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
|
@ -42,7 +43,7 @@ const notificationStyles = {
|
|||
fontFamily: 'Averta',
|
||||
fontSize: '14px',
|
||||
lineHeight: 1.43,
|
||||
color: '#001428',
|
||||
color: fontColor,
|
||||
minHeight: '58px',
|
||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
|
@ -51,7 +52,7 @@ const notificationStyles = {
|
|||
fontFamily: 'Averta',
|
||||
fontSize: '14px',
|
||||
lineHeight: 1.43,
|
||||
color: '#001428',
|
||||
color: fontColor,
|
||||
minHeight: '58px',
|
||||
boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
|
|
|
@ -55,7 +55,7 @@ export const decodeParamsFromSafeMethod = async (data: string) => {
|
|||
case '0xe318b52b':
|
||||
return {
|
||||
methodName: METHOD_TO_ID[methodId],
|
||||
args: web3.eth.abi.decodeParameters(['address', 'address', 'address'], params),
|
||||
args: web3.eth.abi.decodeParameters(['uint', 'address', 'address'], params),
|
||||
}
|
||||
|
||||
// addOwnerWithThreshold
|
||||
|
|
|
@ -13,10 +13,15 @@ export const sameAddress = (firstAddress: string, secondAddress: string): boolea
|
|||
return firstAddress.toLowerCase() === secondAddress.toLowerCase()
|
||||
}
|
||||
|
||||
export const shortVersionOf = (address: string, cut: number) => {
|
||||
const final = 42 - cut
|
||||
export const shortVersionOf = (value: string, cut: number) => {
|
||||
if (!value) {
|
||||
return 'Unknown'
|
||||
}
|
||||
|
||||
if (!address) return 'Unknown address'
|
||||
if (address.length < final) return address
|
||||
return `${address.substring(0, cut)}...${address.substring(final)}`
|
||||
const final = value.length - cut
|
||||
if (value.length < 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 DetailsForm, { safeFieldsValidation } from '~/routes/load/components/DetailsForm'
|
||||
import { history } from '~/store'
|
||||
import { secondary } from '~/theme/variables'
|
||||
import { secondary, sm } from '~/theme/variables'
|
||||
import { type SelectorProps } from '~/routes/load/container/selector'
|
||||
|
||||
const getSteps = () => ['Name and address', 'Owners', 'Review']
|
||||
|
@ -21,7 +21,7 @@ export type LayoutProps = SelectorProps & {
|
|||
|
||||
const iconStyle = {
|
||||
color: secondary,
|
||||
padding: '8px',
|
||||
padding: sm,
|
||||
marginRight: '5px',
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import SafeNameField from '~/routes/open/components/SafeNameForm'
|
|||
import SafeOwnersFields from '~/routes/open/components/SafeOwnersConfirmationsForm'
|
||||
import { getOwnerNameBy, getOwnerAddressBy, FIELD_CONFIRMATIONS } from '~/routes/open/components/fields'
|
||||
import { history } from '~/store'
|
||||
import { secondary } from '~/theme/variables'
|
||||
import { secondary, sm } from '~/theme/variables'
|
||||
|
||||
const getSteps = () => ['Name', 'Owners and confirmations', 'Review']
|
||||
|
||||
|
@ -30,7 +30,7 @@ type Props = {
|
|||
|
||||
const iconStyle = {
|
||||
color: secondary,
|
||||
padding: '8px',
|
||||
padding: sm,
|
||||
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',
|
||||
},
|
||||
close: {
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
height: lg,
|
||||
width: lg,
|
||||
fill: secondaryText,
|
||||
},
|
||||
qrContainer: {
|
||||
|
@ -48,7 +48,7 @@ const styles = () => ({
|
|||
justifyContent: 'center',
|
||||
'& > button': {
|
||||
fontFamily: 'Averta',
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
},
|
||||
},
|
||||
|
|
|
@ -22,7 +22,7 @@ const styles = () => ({
|
|||
maxHeight: '75px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
@ -31,7 +31,7 @@ const styles = () => ({
|
|||
buttonColumn: {
|
||||
padding: '52px 0',
|
||||
'& > button': {
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
fontFamily: 'Averta',
|
||||
},
|
||||
},
|
||||
|
|
|
@ -23,6 +23,7 @@ import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers'
|
|||
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||
import ArrowDown from '../assets/arrow-down.svg'
|
||||
import { styles } from './style'
|
||||
import { sm } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
onClose: () => void,
|
||||
|
@ -106,7 +107,7 @@ const ReviewCustomTx = ({
|
|||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||
<Row margin="md">
|
||||
<Col xs={1}>
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||
</Col>
|
||||
<Col xs={11} center="xs" layout="column">
|
||||
<Hairline />
|
||||
|
|
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
@ -50,7 +50,7 @@ export const styles = () => ({
|
|||
justifyContent: 'center',
|
||||
'& > button': {
|
||||
fontFamily: 'Averta',
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
},
|
||||
submitButton: {
|
||||
|
|
|
@ -28,6 +28,7 @@ import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions'
|
|||
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
||||
import ArrowDown from '../assets/arrow-down.svg'
|
||||
import { styles } from './style'
|
||||
import { sm } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
onClose: () => void,
|
||||
|
@ -136,7 +137,7 @@ const ReviewTx = ({
|
|||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||
<Row margin="md">
|
||||
<Col xs={1}>
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||
</Col>
|
||||
<Col xs={11} center="xs" layout="column">
|
||||
<Hairline />
|
||||
|
|
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
@ -37,7 +37,7 @@ export const styles = () => ({
|
|||
justifyContent: 'center',
|
||||
'& > button': {
|
||||
fontFamily: 'Averta',
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
},
|
||||
submitButton: {
|
||||
|
|
|
@ -25,6 +25,7 @@ import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo'
|
|||
import QRIcon from '~/assets/icons/qrcode.svg'
|
||||
import ArrowDown from '../assets/arrow-down.svg'
|
||||
import { styles } from './style'
|
||||
import { sm } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
onClose: () => void,
|
||||
|
@ -102,7 +103,7 @@ const SendCustomTx = ({
|
|||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||
<Row margin="md">
|
||||
<Col xs={1}>
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||
</Col>
|
||||
<Col xs={11} center="xs" layout="column">
|
||||
<Hairline />
|
||||
|
|
|
@ -15,7 +15,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
@ -32,7 +32,7 @@ export const styles = () => ({
|
|||
justifyContent: 'center',
|
||||
'& > button': {
|
||||
fontFamily: 'Averta',
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
},
|
||||
submitButton: {
|
||||
|
|
|
@ -28,6 +28,7 @@ import ScanQRModal from '~/components/ScanQRModal'
|
|||
import ArrowDown from '../assets/arrow-down.svg'
|
||||
import QRIcon from '~/assets/icons/qrcode.svg'
|
||||
import { styles } from './style'
|
||||
import { sm } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
onClose: () => void,
|
||||
|
@ -114,7 +115,7 @@ const SendFunds = ({
|
|||
<SafeInfo safeAddress={safeAddress} safeName={safeName} ethBalance={ethBalance} />
|
||||
<Row margin="md">
|
||||
<Col xs={1}>
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: sm }} />
|
||||
</Col>
|
||||
<Col xs={11} center="xs" layout="column">
|
||||
<Hairline />
|
||||
|
|
|
@ -15,7 +15,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
@ -32,7 +32,7 @@ export const styles = () => ({
|
|||
justifyContent: 'center',
|
||||
'& > button': {
|
||||
fontFamily: 'Averta',
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
},
|
||||
submitButton: {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// @flow
|
||||
import { lg } from '~/theme/variables'
|
||||
import { lg, md } from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
title: {
|
||||
padding: `${lg} 0 20px`,
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
formContainer: {
|
||||
padding: '0 20px',
|
||||
|
|
|
@ -63,6 +63,11 @@ class Balances extends React.Component<Props, State> {
|
|||
props.fetchTokens()
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
const { activateTokensByBalance, safeAddress } = this.props
|
||||
activateTokensByBalance(safeAddress)
|
||||
}
|
||||
|
||||
onShow = (action: Action) => () => {
|
||||
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() {
|
||||
const {
|
||||
showToken, showReceive, sendFunds,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import { sm, md } from '~/theme/variables'
|
||||
import { xs, sm, md } from '~/theme/variables'
|
||||
|
||||
export const styles = (theme: Object) => ({
|
||||
root: {
|
||||
|
@ -41,7 +41,7 @@ export const styles = (theme: Object) => ({
|
|||
width: '95px',
|
||||
minWidth: '95px',
|
||||
marginLeft: sm,
|
||||
borderRadius: '4px',
|
||||
borderRadius: xs,
|
||||
'& > span': {
|
||||
fontSize: '14px',
|
||||
},
|
||||
|
@ -49,7 +49,7 @@ export const styles = (theme: Object) => ({
|
|||
send: {
|
||||
width: '75px',
|
||||
minWidth: '75px',
|
||||
borderRadius: '4px',
|
||||
borderRadius: xs,
|
||||
'& > span': {
|
||||
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',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||
lineHeight: 'normal',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -17,14 +17,14 @@ export const styles = () => ({
|
|||
lineHeight: 'normal',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
width: '35px',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
formContainer: {
|
||||
padding: `${md} ${lg}`,
|
||||
|
|
|
@ -10,7 +10,7 @@ export const styles = () => ({
|
|||
boxSizing: 'border-box',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
container: {
|
||||
padding: `${md} ${lg}`,
|
||||
|
|
|
@ -17,7 +17,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
address: {
|
||||
marginRight: sm,
|
||||
|
|
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -17,14 +17,14 @@ export const styles = () => ({
|
|||
marginLeft: '20px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
width: '35px',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '16px',
|
||||
fontSize: md,
|
||||
},
|
||||
formContainer: {
|
||||
padding: `${md} ${lg}`,
|
||||
|
|
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||
marginRight: sm,
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -20,7 +20,7 @@ export const styles = () => ({
|
|||
lineHeight: 'normal',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
address: {
|
||||
marginRight: sm,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import { lg } from '~/theme/variables'
|
||||
import { lg, sm } from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
formContainer: {
|
||||
|
@ -40,7 +40,7 @@ export const styles = () => ({
|
|||
controlsRow: {
|
||||
backgroundColor: 'white',
|
||||
padding: lg,
|
||||
borderRadius: '8px',
|
||||
borderRadius: sm,
|
||||
},
|
||||
removeOwnerIcon: {
|
||||
marginLeft: lg,
|
||||
|
|
|
@ -18,11 +18,11 @@ import Link from '~/components/layout/Link'
|
|||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import actions, { type Actions } from './actions'
|
||||
import { secondary } from '~/theme/variables'
|
||||
import { secondary, md } from '~/theme/variables'
|
||||
import { styles } from './style'
|
||||
|
||||
const openIconStyle = {
|
||||
height: '16px',
|
||||
height: md,
|
||||
color: secondary,
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ export const styles = () => ({
|
|||
minHeight: '369px',
|
||||
},
|
||||
manage: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
close: {
|
||||
height: '35px',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import {
|
||||
fontColor, lg, smallFontSize, border, secondaryText,
|
||||
fontColor, xl, lg, smallFontSize, border, secondaryText,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
|
@ -24,7 +24,7 @@ export const styles = () => ({
|
|||
borderTop: `2px solid ${border}`,
|
||||
},
|
||||
modifyBtn: {
|
||||
height: '32px',
|
||||
height: xl,
|
||||
fontSize: smallFontSize,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -10,7 +10,7 @@ export const styles = () => ({
|
|||
minHeight: '505px',
|
||||
marginBottom: '54px',
|
||||
display: 'flex',
|
||||
borderRadius: '8px',
|
||||
borderRadius: sm,
|
||||
},
|
||||
settings: {
|
||||
letterSpacing: '-0.5px',
|
||||
|
@ -25,7 +25,7 @@ export const styles = () => ({
|
|||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
'&:first-child': {
|
||||
borderTopLeftRadius: '8px',
|
||||
borderTopLeftRadius: sm,
|
||||
},
|
||||
},
|
||||
active: {
|
||||
|
@ -57,7 +57,7 @@ export const styles = () => ({
|
|||
},
|
||||
removeSafeIcon: {
|
||||
marginLeft: sm,
|
||||
height: '16px',
|
||||
height: md,
|
||||
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',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -11,7 +11,7 @@ export const styles = () => ({
|
|||
maxHeight: '75px',
|
||||
},
|
||||
headingText: {
|
||||
fontSize: '24px',
|
||||
fontSize: lg,
|
||||
},
|
||||
closeIcon: {
|
||||
height: '35px',
|
||||
|
|
|
@ -1,36 +1,25 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
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 Button from '~/components/layout/Button'
|
||||
import { sm, lg, background } from '~/theme/variables'
|
||||
|
||||
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
||||
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
||||
import { xl, sm, border } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
onTxConfirm: Function,
|
||||
onTxCancel: Function,
|
||||
onTxExecute: Function,
|
||||
classes: Object,
|
||||
showConfirmBtn: boolean,
|
||||
onTxCancel: Function,
|
||||
showCancelBtn: boolean,
|
||||
showExecuteBtn: boolean,
|
||||
}
|
||||
|
||||
const styles = () => ({
|
||||
buttonRow: {
|
||||
height: '56px',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: background,
|
||||
borderTop: `2px solid ${border}`,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
padding: '10px 20px',
|
||||
},
|
||||
button: {
|
||||
height: '32px',
|
||||
'&:last-child': {
|
||||
marginLeft: lg,
|
||||
},
|
||||
height: xl,
|
||||
},
|
||||
icon: {
|
||||
width: '14px',
|
||||
|
@ -42,46 +31,12 @@ const styles = () => ({
|
|||
const ButtonRow = ({
|
||||
classes,
|
||||
onTxCancel,
|
||||
onTxConfirm,
|
||||
showConfirmBtn,
|
||||
showCancelBtn,
|
||||
showExecuteBtn,
|
||||
onTxExecute,
|
||||
}: Props) => (
|
||||
<Row align="center" className={classes.buttonRow}>
|
||||
<Row align="right" className={classes.buttonRow}>
|
||||
{showCancelBtn && (
|
||||
<Button className={classes.button} variant="contained" minWidth={140} color="secondary" onClick={onTxCancel}>
|
||||
<BlockIcon className={classes.icon} />
|
||||
{' '}
|
||||
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
|
||||
Cancel tx
|
||||
</Button>
|
||||
)}
|
||||
</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
|
||||
import React, { useState } from 'react'
|
||||
import React from 'react'
|
||||
import cn from 'classnames'
|
||||
import { List } from 'immutable'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Tabs from '@material-ui/core/Tabs'
|
||||
import Tab from '@material-ui/core/Tab'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Col from '~/components/layout/Col'
|
||||
import Row from '~/components/layout/Row'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import Img from '~/components/layout/Img'
|
||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions/send'
|
||||
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
||||
import OwnersList from './List'
|
||||
import OwnersList from './OwnersList'
|
||||
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'
|
||||
|
||||
type Props = {
|
||||
|
@ -29,7 +31,10 @@ type Props = {
|
|||
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 = ({
|
||||
tx,
|
||||
|
@ -44,31 +49,26 @@ const OwnersColumn = ({
|
|||
onTxCancel,
|
||||
onTxExecute,
|
||||
}: Props) => {
|
||||
const [tabIndex, setTabIndex] = useState(0)
|
||||
const handleTabChange = (event, tabClicked) => {
|
||||
setTabIndex(tabClicked)
|
||||
}
|
||||
|
||||
const cancellationTx = isCancellationTransaction(tx, safeAddress)
|
||||
|
||||
const ownersWhoConfirmed = []
|
||||
let currentUserAlreadyConfirmed = false
|
||||
let executionConfirmation
|
||||
|
||||
tx.confirmations.forEach((conf) => {
|
||||
if (conf.owner.address === userAddress) {
|
||||
currentUserAlreadyConfirmed = true
|
||||
}
|
||||
|
||||
if (conf.type === TX_TYPE_CONFIRMATION) {
|
||||
ownersWhoConfirmed.push(conf.owner)
|
||||
} else {
|
||||
executionConfirmation = conf.owner
|
||||
}
|
||||
})
|
||||
const ownersUnconfirmed = owners.filter(
|
||||
(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
|
||||
if (tx.executionTxHash) {
|
||||
|
@ -83,33 +83,51 @@ const OwnersColumn = ({
|
|||
displayButtonRow = false
|
||||
}
|
||||
|
||||
let confirmedLabel = `Confirmed [${tx.confirmations.size}/${threshold}]`
|
||||
if (tx.executionTxHash) {
|
||||
confirmedLabel = `Confirmed [${tx.confirmations.size}]`
|
||||
}
|
||||
const unconfirmedLabel = `Unconfirmed [${ownersUnconfirmed.size}]`
|
||||
const showConfirmBtn = !tx.isExecuted
|
||||
&& !tx.cancelled
|
||||
&& userIsUnconfirmedOwner
|
||||
&& !currentUserAlreadyConfirmed
|
||||
&& !thresholdReached
|
||||
|
||||
return (
|
||||
<Col xs={6} className={classes.rightCol} layout="block">
|
||||
<Row>
|
||||
<Tabs value={tabIndex} onChange={handleTabChange} indicatorColor="secondary" textColor="secondary">
|
||||
<Tab label={confirmedLabel} />
|
||||
<Tab label={unconfirmedLabel} />
|
||||
</Tabs>
|
||||
<Hairline color="#d4d53d" />
|
||||
</Row>
|
||||
<Row>
|
||||
{tabIndex === 0 && <OwnersList owners={ownersWhoConfirmed} executionConfirmation={executionConfirmation} />}
|
||||
</Row>
|
||||
<Row>{tabIndex === 1 && <OwnersList owners={ownersUnconfirmed} />}</Row>
|
||||
<Block className={cn(classes.ownerListTitle, (thresholdReached || tx.isExecuted) && classes.ownerListTitleDone)}>
|
||||
<div className={classes.iconState}>
|
||||
{thresholdReached || tx.isExecuted
|
||||
? <Img src={CheckLargeFilledGreenIcon} />
|
||||
: <Img src={ConfirmLargeGreenIcon} />}
|
||||
</div>
|
||||
{tx.isExecuted
|
||||
? `Confirmed [${tx.confirmations.size}/${tx.confirmations.size}]`
|
||||
: `Confirmed [${tx.confirmations.size}/${threshold}]`}
|
||||
</Block>
|
||||
<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 && (
|
||||
<ButtonRow
|
||||
onTxConfirm={onTxConfirm}
|
||||
onTxCancel={onTxCancel}
|
||||
showConfirmBtn={!currentUserAlreadyConfirmed && !thresholdReached}
|
||||
showCancelBtn={!cancellationTx}
|
||||
showExecuteBtn={thresholdReached}
|
||||
onTxExecute={onTxExecute}
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// @flow
|
||||
import { border, sm } from '~/theme/variables'
|
||||
import {
|
||||
border, sm, boldFont, primary, secondary, secondaryText,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
ownersList: {
|
||||
|
@ -10,7 +12,23 @@ export const styles = () => ({
|
|||
},
|
||||
rightCol: {
|
||||
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: {
|
||||
marginRight: sm,
|
||||
|
@ -18,4 +36,57 @@ export const styles = () => ({
|
|||
owner: {
|
||||
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) => (
|
||||
<Paragraph noMargin data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
||||
<Block data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
||||
<Bold>
|
||||
Send
|
||||
{' '}
|
||||
|
@ -60,33 +60,31 @@ const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProp
|
|||
{' '}
|
||||
to:
|
||||
</Bold>
|
||||
<br />
|
||||
<EtherscanLink type="address" value={recipient} />
|
||||
</Paragraph>
|
||||
</Block>
|
||||
)
|
||||
|
||||
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
||||
<>
|
||||
{removedOwner && (
|
||||
<Paragraph data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
||||
<Block data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
||||
<Bold>Remove owner:</Bold>
|
||||
<br />
|
||||
<EtherscanLink type="address" value={removedOwner} />
|
||||
</Paragraph>
|
||||
</Block>
|
||||
)}
|
||||
{addedOwner && (
|
||||
<Paragraph data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
||||
<Block data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
||||
<Bold>Add owner:</Bold>
|
||||
<br />
|
||||
<EtherscanLink type="address" value={addedOwner} />
|
||||
</Paragraph>
|
||||
</Block>
|
||||
)}
|
||||
{newThreshold && (
|
||||
<Paragraph data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
||||
<Block data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
||||
<Bold>Change required confirmations:</Bold>
|
||||
<br />
|
||||
{newThreshold}
|
||||
</Paragraph>
|
||||
<Paragraph size="md" noMargin>
|
||||
{newThreshold}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
@ -95,7 +93,7 @@ const CustomDescription = ({
|
|||
data, value = 0, recipient, classes,
|
||||
}: CustomDescProps) => (
|
||||
<>
|
||||
<Paragraph noMargin data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
||||
<Block data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
||||
<Bold>
|
||||
Send
|
||||
{' '}
|
||||
|
@ -105,22 +103,21 @@ const CustomDescription = ({
|
|||
{' '}
|
||||
to:
|
||||
</Bold>
|
||||
<br />
|
||||
<EtherscanLink type="address" value={recipient} />
|
||||
</Paragraph>
|
||||
<Paragraph className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
||||
</Block>
|
||||
<Block className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
||||
<Bold>Data (hex encoded):</Bold>
|
||||
<br />
|
||||
{data}
|
||||
</Paragraph>
|
||||
<Paragraph size="md" noMargin>
|
||||
{data}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
</>
|
||||
)
|
||||
|
||||
const TxDescription = ({ tx, classes }: Props) => {
|
||||
const {
|
||||
recipient, value, modifySettingsTx, removedOwner, addedOwner, newThreshold, cancellationTx, customTx, data,
|
||||
recipient, value, modifySettingsTx, removedOwner, addedOwner, newThreshold, cancellationTx, customTx, creationTx, data,
|
||||
} = getTxData(tx)
|
||||
|
||||
return (
|
||||
<Block className={classes.txDataContainer}>
|
||||
{modifySettingsTx && (
|
||||
|
@ -129,7 +126,7 @@ const TxDescription = ({ tx, classes }: Props) => {
|
|||
{customTx && (
|
||||
<CustomDescription data={data} value={value} recipient={recipient} classes={classes} />
|
||||
)}
|
||||
{!cancellationTx && !modifySettingsTx && !customTx && (
|
||||
{!cancellationTx && !modifySettingsTx && !customTx && !creationTx && (
|
||||
<TransferDescription value={value} symbol={tx.symbol} recipient={recipient} />
|
||||
)}
|
||||
</Block>
|
||||
|
|
|
@ -11,6 +11,7 @@ type DecodedTxData = {
|
|||
addedOwner?: string,
|
||||
cancellationTx?: boolean,
|
||||
customTx?: boolean,
|
||||
creationTx?: boolean,
|
||||
data: string,
|
||||
}
|
||||
|
||||
|
@ -54,6 +55,8 @@ export const getTxData = (tx: Transaction): DecodedTxData => {
|
|||
}
|
||||
} else if (tx.cancellationTx) {
|
||||
txData.cancellationTx = true
|
||||
} else if (tx.creationTx) {
|
||||
txData.creationTx = true
|
||||
} else {
|
||||
txData.recipient = tx.recipient
|
||||
txData.value = 0
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import React, { useState } from 'react'
|
||||
import { List } from 'immutable'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||
import Row from '~/components/layout/Row'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Col from '~/components/layout/Col'
|
||||
|
@ -10,11 +9,9 @@ import Bold from '~/components/layout/Bold'
|
|||
import Span from '~/components/layout/Span'
|
||||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import EtherScanLink from '~/components/EtherscanLink'
|
||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||
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 OwnersColumn from './OwnersColumn'
|
||||
import CancelTxModal from './CancelTxModal'
|
||||
|
@ -36,16 +33,13 @@ type Props = {
|
|||
|
||||
type OpenModal = 'cancelTx' | 'approveTx' | null
|
||||
|
||||
const openIconStyle = {
|
||||
height: '13px',
|
||||
color: secondary,
|
||||
}
|
||||
|
||||
const txStatusToLabel = {
|
||||
success: 'Success',
|
||||
awaiting_your_confirmation: 'Awaiting your confirmation',
|
||||
awaiting_confirmations: 'Awaiting confirmations',
|
||||
cancelled: 'Cancelled',
|
||||
awaiting_execution: 'Awaiting execution',
|
||||
pending: 'Pending',
|
||||
}
|
||||
|
||||
const ExpandedTx = ({
|
||||
|
@ -67,24 +61,21 @@ const ExpandedTx = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Block>
|
||||
<Block className={classes.expandedTxBlock}>
|
||||
<Row>
|
||||
<Col xs={6} layout="column">
|
||||
<Block className={classes.txDataContainer}>
|
||||
<Paragraph noMargin>
|
||||
<Bold>TX hash: </Bold>
|
||||
<Block align="left" className={classes.txData}>
|
||||
<Bold className={classes.txHash}>TX hash:</Bold>
|
||||
{tx.executionTxHash ? (
|
||||
<a href={getEtherScanLink('tx', tx.executionTxHash)} target="_blank" rel="noopener noreferrer">
|
||||
{shortVersionOf(tx.executionTxHash, 4)}
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</a>
|
||||
<EtherScanLink type="tx" value={tx.executionTxHash} cut={8} />
|
||||
) : (
|
||||
'n/a'
|
||||
)}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Paragraph noMargin>
|
||||
<Bold>TX status: </Bold>
|
||||
<Span className={classes[tx.status]} style={{ fontWeight: 'bold' }}>
|
||||
<Span>
|
||||
{txStatusToLabel[tx.status]}
|
||||
</Span>
|
||||
</Paragraph>
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
// @flow
|
||||
import {
|
||||
md, lg, connected, error, disabled,
|
||||
md, lg, connected, error, disabled, border,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
expandedTxBlock: {
|
||||
borderBottom: `2px solid ${border}`,
|
||||
},
|
||||
txDataContainer: {
|
||||
padding: `${lg} ${md}`,
|
||||
},
|
||||
txData: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
awaiting_your_confirmation: {
|
||||
color: disabled,
|
||||
},
|
||||
awaiting_confirmations: {
|
||||
color: disabled,
|
||||
},
|
||||
|
@ -19,4 +29,7 @@ export const styles = () => ({
|
|||
cancelled: {
|
||||
color: error,
|
||||
},
|
||||
txHash: {
|
||||
paddingRight: '3px',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -19,6 +19,7 @@ type Props = {
|
|||
const statusToIcon = {
|
||||
success: OkIcon,
|
||||
cancelled: ErrorIcon,
|
||||
awaiting_your_confirmation: AwaitingIcon,
|
||||
awaiting_confirmations: AwaitingIcon,
|
||||
awaiting_execution: AwaitingIcon,
|
||||
pending: <CircularProgress size={14} />,
|
||||
|
@ -26,9 +27,10 @@ const statusToIcon = {
|
|||
|
||||
const statusToLabel = {
|
||||
success: 'Success',
|
||||
cancelled: 'Cancelled',
|
||||
awaiting_confirmations: 'Awaiting',
|
||||
awaiting_execution: 'Awaiting',
|
||||
cancelled: 'Failed',
|
||||
awaiting_your_confirmation: 'Awaiting your confirmation',
|
||||
awaiting_confirmations: 'Awaiting confirmations',
|
||||
awaiting_execution: 'Awaiting execution',
|
||||
pending: 'Pending',
|
||||
}
|
||||
|
||||
|
@ -45,7 +47,7 @@ const Status = ({ classes, status }: Props) => {
|
|||
{typeof Icon === 'object' ? (
|
||||
Icon
|
||||
) : (
|
||||
<Img src={Icon} alt="OK Icon" style={statusIconStyle} />
|
||||
<Img src={Icon} alt={statusToLabel[status]} style={statusIconStyle} />
|
||||
)}
|
||||
<Paragraph noMargin className={classes.statusText}>
|
||||
{statusToLabel[status]}
|
||||
|
|
|
@ -1,32 +1,40 @@
|
|||
// @flow
|
||||
import {
|
||||
smallFontSize, boldFont, sm, error, disabled, primary,
|
||||
boldFont, sm, lg, error, disabled, extraSmallFontSize, secondary,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
fontSize: smallFontSize,
|
||||
fontSize: extraSmallFontSize,
|
||||
fontWeight: boldFont,
|
||||
width: '100px',
|
||||
padding: sm,
|
||||
alignItems: 'center',
|
||||
boxSizing: 'border-box',
|
||||
height: lg,
|
||||
marginTop: sm,
|
||||
marginBottom: sm,
|
||||
borderRadius: '3px',
|
||||
},
|
||||
success: {
|
||||
backgroundColor: '#A1D2CA',
|
||||
color: primary,
|
||||
color: secondary,
|
||||
},
|
||||
cancelled: {
|
||||
backgroundColor: 'transparent',
|
||||
color: error,
|
||||
border: `1px solid ${error}`,
|
||||
},
|
||||
awaiting_your_confirmation: {
|
||||
backgroundColor: '#d4d5d3',
|
||||
color: disabled,
|
||||
},
|
||||
awaiting_confirmations: {
|
||||
backgroundColor: '#dfebff',
|
||||
backgroundColor: '#d4d5d3',
|
||||
color: disabled,
|
||||
},
|
||||
awaiting_execution: {
|
||||
backgroundColor: '#dfebff',
|
||||
backgroundColor: '#d4d5d3',
|
||||
color: disabled,
|
||||
},
|
||||
pending: {
|
||||
|
@ -34,7 +42,6 @@ export const styles = () => ({
|
|||
color: '#e8673c',
|
||||
},
|
||||
statusText: {
|
||||
marginLeft: 'auto',
|
||||
textTransform: 'uppercase',
|
||||
padding: '0 7px',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -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
|
||||
import React from 'react'
|
||||
import { format, getTime, parseISO } from 'date-fns'
|
||||
import { BigNumber } from 'bignumber.js'
|
||||
import { List } from 'immutable'
|
||||
import TxType from './TxType'
|
||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||
import { type SortRow, buildOrderFieldFrom } from '~/components/Table/sorting'
|
||||
import { type Column } from '~/components/Table/TableHead'
|
||||
|
@ -17,7 +19,7 @@ export const TX_TABLE_EXPAND_ICON = 'expand'
|
|||
|
||||
type TxData = {
|
||||
nonce: number,
|
||||
type: string,
|
||||
type: React.ReactNode,
|
||||
date: string,
|
||||
amount: number | string,
|
||||
tx: Transaction,
|
||||
|
@ -47,20 +49,31 @@ export type TransactionRow = SortRow<TxData>
|
|||
export const getTxTableData = (transactions: List<Transaction>): List<TransactionRow> => {
|
||||
const rows = transactions.map((tx: Transaction) => {
|
||||
const txDate = tx.isExecuted ? tx.executionDate : tx.submissionDate
|
||||
let txType = 'Outgoing transfer'
|
||||
let txType = 'outgoing'
|
||||
if (tx.modifySettingsTx) {
|
||||
txType = 'Modify Safe Settings'
|
||||
txType = 'settings'
|
||||
} else if (tx.cancellationTx) {
|
||||
txType = 'Cancellation transaction'
|
||||
txType = 'cancellation'
|
||||
} 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 {
|
||||
[TX_TABLE_NONCE_ID]: tx.nonce,
|
||||
[TX_TABLE_TYPE_ID]: txType,
|
||||
[TX_TABLE_DATE_ID]: formatDate(tx.isExecuted ? tx.executionDate : tx.submissionDate),
|
||||
[buildOrderFieldFrom(TX_TABLE_DATE_ID)]: getTime(parseISO(txDate)),
|
||||
[TX_TABLE_NONCE_ID]: txIndex,
|
||||
[TX_TABLE_TYPE_ID]: <TxType txType={txType} />,
|
||||
[TX_TABLE_DATE_ID]: tx.isExecuted
|
||||
? 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_STATUS_ID]: tx.status,
|
||||
[TX_TABLE_RAW_TX_ID]: tx,
|
||||
|
@ -74,7 +87,7 @@ export const generateColumns = () => {
|
|||
const nonceColumn: Column = {
|
||||
id: TX_TABLE_NONCE_ID,
|
||||
disablePadding: false,
|
||||
label: 'Nonce',
|
||||
label: 'Id',
|
||||
custom: false,
|
||||
order: false,
|
||||
width: 50,
|
||||
|
@ -95,7 +108,7 @@ export const generateColumns = () => {
|
|||
disablePadding: false,
|
||||
label: 'Amount',
|
||||
custom: false,
|
||||
width: 100,
|
||||
width: 120,
|
||||
}
|
||||
|
||||
const dateColumn: Column = {
|
||||
|
@ -112,6 +125,7 @@ export const generateColumns = () => {
|
|||
disablePadding: false,
|
||||
label: 'Status',
|
||||
custom: true,
|
||||
align: 'right',
|
||||
}
|
||||
|
||||
const expandIconColumn: Column = {
|
||||
|
|
|
@ -26,7 +26,7 @@ export const TRANSACTION_ROW_TEST_ID = 'transaction-row'
|
|||
|
||||
const expandCellStyle = {
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingRight: 15,
|
||||
}
|
||||
|
||||
type Props = {
|
||||
|
@ -68,6 +68,7 @@ const TxsTable = ({
|
|||
label="Transactions"
|
||||
defaultOrderBy={TX_TABLE_DATE_ID}
|
||||
defaultOrder="desc"
|
||||
defaultRowsPerPage={25}
|
||||
columns={columns}
|
||||
data={filteredData}
|
||||
size={filteredData.size}
|
||||
|
@ -84,7 +85,7 @@ const TxsTable = ({
|
|||
{autoColumns.map((column: Column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
className={classes.cell}
|
||||
className={cn(classes.cell, row.status === 'cancelled' && classes.cancelledRow)}
|
||||
style={cellWidth(column.width)}
|
||||
align={column.align}
|
||||
component="td"
|
||||
|
@ -98,31 +99,37 @@ const TxsTable = ({
|
|||
</Row>
|
||||
</TableCell>
|
||||
<TableCell style={expandCellStyle}>
|
||||
<IconButton disableRipple>{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<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}
|
||||
/>
|
||||
{!row.tx.creationTx && (
|
||||
<IconButton disableRipple>
|
||||
{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}
|
||||
</IconButton>
|
||||
)}
|
||||
</TableCell>
|
||||
</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>
|
||||
))}
|
||||
</Table>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// @flow
|
||||
import { lg } from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
container: {
|
||||
marginTop: lg,
|
||||
marginTop: '70px',
|
||||
},
|
||||
row: {
|
||||
cursor: 'pointer',
|
||||
|
@ -14,11 +12,19 @@ export const styles = () => ({
|
|||
expandedRow: {
|
||||
backgroundColor: '#fff3e2',
|
||||
},
|
||||
cancelledRow: {
|
||||
opacity: 0.4,
|
||||
},
|
||||
extendedTxContainer: {
|
||||
padding: 0,
|
||||
border: 0,
|
||||
'&:last-child': {
|
||||
padding: 0,
|
||||
},
|
||||
backgroundColor: '#fffaf4',
|
||||
},
|
||||
actions: {
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
import React, { useEffect } from 'react'
|
||||
import { List } from 'immutable'
|
||||
import NoTransactions from '~/routes/safe/components/Transactions/NoTransactions'
|
||||
import TxsTable from '~/routes/safe/components/Transactions/TxsTable'
|
||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||
|
@ -19,6 +18,8 @@ type Props = {
|
|||
currentNetwork: string,
|
||||
}
|
||||
|
||||
const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000
|
||||
|
||||
const Transactions = ({
|
||||
transactions = List(),
|
||||
owners,
|
||||
|
@ -31,30 +32,30 @@ const Transactions = ({
|
|||
fetchTransactions,
|
||||
currentNetwork,
|
||||
}: Props) => {
|
||||
let intervalId: IntervalID
|
||||
|
||||
useEffect(() => {
|
||||
fetchTransactions(safeAddress)
|
||||
|
||||
intervalId = setInterval(() => {
|
||||
fetchTransactions(safeAddress)
|
||||
}, TIMEOUT)
|
||||
|
||||
return () => clearInterval(intervalId)
|
||||
}, [safeAddress])
|
||||
|
||||
const hasTransactions = transactions.size > 0
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasTransactions ? (
|
||||
<TxsTable
|
||||
transactions={transactions}
|
||||
threshold={threshold}
|
||||
owners={owners}
|
||||
userAddress={userAddress}
|
||||
currentNetwork={currentNetwork}
|
||||
granted={granted}
|
||||
safeAddress={safeAddress}
|
||||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
/>
|
||||
) : (
|
||||
<NoTransactions />
|
||||
)}
|
||||
</>
|
||||
<TxsTable
|
||||
transactions={transactions}
|
||||
threshold={threshold}
|
||||
owners={owners}
|
||||
userAddress={userAddress}
|
||||
currentNetwork={currentNetwork}
|
||||
granted={granted}
|
||||
safeAddress={safeAddress}
|
||||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -33,17 +33,22 @@ export type SelectorProps = {
|
|||
transactions: List<Transaction>,
|
||||
}
|
||||
|
||||
const getTxStatus = (tx: Transaction, safe: Safe): TransactionStatus => {
|
||||
let txStatus = 'awaiting_confirmations'
|
||||
|
||||
const getTxStatus = (tx: Transaction, userAddress: string, safe: Safe): TransactionStatus => {
|
||||
let txStatus
|
||||
if (tx.executionTxHash) {
|
||||
txStatus = 'success'
|
||||
} else if (tx.cancelled) {
|
||||
txStatus = 'cancelled'
|
||||
} else if (tx.confirmations.size === safe.threshold) {
|
||||
txStatus = 'awaiting_execution'
|
||||
} else if (tx.creationTx) {
|
||||
txStatus = 'success'
|
||||
} else if (!tx.confirmations.size) {
|
||||
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
|
||||
|
@ -108,8 +113,9 @@ const extendedSafeTokensSelector: Selector<GlobalState, RouterProps, List<Token>
|
|||
|
||||
const extendedTransactionsSelector: Selector<GlobalState, RouterProps, List<Transaction>> = createSelector(
|
||||
safeSelector,
|
||||
userAccountSelector,
|
||||
safeTransactionsSelector,
|
||||
(safe, transactions) => {
|
||||
(safe, userAddress, transactions) => {
|
||||
const extendedTransactions = transactions.map((tx: Transaction) => {
|
||||
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
|
||||
let replacementTransaction
|
||||
if (!tx.isExecuted) {
|
||||
replacementTransaction = transactions.findLast(
|
||||
(transaction) => transaction.isExecuted && transaction.nonce >= tx.nonce,
|
||||
replacementTransaction = transactions.size > 1 && transactions.findLast(
|
||||
(transaction) => (
|
||||
transaction.isExecuted && transaction.nonce && transaction.nonce >= tx.nonce
|
||||
),
|
||||
)
|
||||
if (replacementTransaction) {
|
||||
extendedTx = tx.set('cancelled', true)
|
||||
}
|
||||
}
|
||||
|
||||
return extendedTx.set('status', getTxStatus(extendedTx, safe))
|
||||
return extendedTx.set('status', getTxStatus(extendedTx, userAddress, safe))
|
||||
})
|
||||
|
||||
return extendedTransactions
|
||||
|
|
|
@ -40,6 +40,7 @@ type TxServiceModel = {
|
|||
refundReceiver: string,
|
||||
safeTxHash: string,
|
||||
submissionDate: string,
|
||||
executor: string,
|
||||
executionDate: string,
|
||||
confirmations: ConfirmationServiceModel[],
|
||||
isExecuted: boolean,
|
||||
|
@ -139,6 +140,7 @@ export const buildTransactionFrom = async (
|
|||
refundParams,
|
||||
isExecuted: tx.isExecuted,
|
||||
submissionDate: tx.submissionDate,
|
||||
executor: tx.executor,
|
||||
executionDate: tx.executionDate,
|
||||
executionTxHash: tx.transactionHash,
|
||||
safeTxHash: tx.safeTxHash,
|
||||
|
@ -147,29 +149,54 @@ export const buildTransactionFrom = async (
|
|||
modifySettingsTx,
|
||||
customTx,
|
||||
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) => {
|
||||
web3 = await getWeb3()
|
||||
|
||||
const url = buildTxServiceUrl(safeAddress)
|
||||
const response = await axios.get(url)
|
||||
const transactions: TxServiceModel[] = response.data.results
|
||||
let transactions: TxServiceModel[] = addMockSafeCreationTx(safeAddress)
|
||||
try {
|
||||
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 txsRecord = await Promise.all(
|
||||
transactions.map((tx: TxServiceModel) => buildTransactionFrom(safeAddress, tx, safeSubjects)),
|
||||
)
|
||||
|
||||
return Map().set(safeAddress, List(txsRecord))
|
||||
}
|
||||
|
||||
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||
try {
|
||||
const transactions: Map<string, List<Transaction>> = await loadSafeTransactions(safeAddress)
|
||||
|
||||
return dispatch(addTransactions(transactions))
|
||||
} catch (err) {
|
||||
console.error(`Requests for transactions for ${safeAddress} failed with 404`)
|
||||
}
|
||||
const transactions: Map<string, List<Transaction>> = await loadSafeTransactions(safeAddress)
|
||||
return dispatch(addTransactions(transactions))
|
||||
}
|
||||
|
|
|
@ -124,8 +124,8 @@ const safeStorageMware = (store: Store<GlobalState>) => (next: Function) => asyn
|
|||
case SET_DEFAULT_SAFE: {
|
||||
if (action.payload) {
|
||||
saveDefaultSafe(action.payload)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
|
@ -4,7 +4,15 @@ import type { RecordFactory, RecordOf } from 'immutable'
|
|||
import { type Confirmation } from '~/routes/safe/store/models/confirmation'
|
||||
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 = {
|
||||
nonce: number,
|
||||
|
@ -25,7 +33,9 @@ export type TransactionProps = {
|
|||
modifySettingsTx: boolean,
|
||||
cancellationTx: boolean,
|
||||
customTx: boolean,
|
||||
creationTx: boolean,
|
||||
safeTxHash: string,
|
||||
executor: string,
|
||||
executionTxHash?: string,
|
||||
decimals?: number,
|
||||
cancelled?: boolean,
|
||||
|
@ -49,6 +59,7 @@ export const makeTransaction: RecordFactory<TransactionProps> = Record({
|
|||
refundReceiver: ZERO_ADDRESS,
|
||||
isExecuted: false,
|
||||
submissionDate: '',
|
||||
executor: '',
|
||||
executionDate: '',
|
||||
symbol: '',
|
||||
executionTxHash: undefined,
|
||||
|
@ -57,6 +68,7 @@ export const makeTransaction: RecordFactory<TransactionProps> = Record({
|
|||
modifySettingsTx: false,
|
||||
cancellationTx: false,
|
||||
customTx: false,
|
||||
creationTx: false,
|
||||
status: 'awaiting',
|
||||
decimals: 18,
|
||||
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,
|
||||
textTransform: 'none',
|
||||
borderRadius: '8px',
|
||||
borderRadius: sm,
|
||||
},
|
||||
contained: {
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
|
@ -102,7 +102,7 @@ export default createMuiTheme({
|
|||
},
|
||||
MuiStepper: {
|
||||
root: {
|
||||
padding: '24px 0 0 15px',
|
||||
padding: `${lg} 0 0 15px`,
|
||||
},
|
||||
},
|
||||
MuiIconButton: {
|
||||
|
@ -238,6 +238,7 @@ export default createMuiTheme({
|
|||
},
|
||||
MuiTablePagination: {
|
||||
toolbar: {
|
||||
paddingRight: '15px',
|
||||
'& > span:nth-child(2)': {
|
||||
order: 1,
|
||||
},
|
||||
|
@ -255,11 +256,11 @@ export default createMuiTheme({
|
|||
input: {
|
||||
order: 2,
|
||||
width: '60px',
|
||||
padding: `0 ${md} 0 0`,
|
||||
color: disabled,
|
||||
},
|
||||
select: {
|
||||
paddingRight: 30,
|
||||
minWidth: '20px',
|
||||
minWidth: lg,
|
||||
},
|
||||
actions: {
|
||||
order: 4,
|
||||
|
@ -270,6 +271,9 @@ export default createMuiTheme({
|
|||
root: {
|
||||
fontSize: extraSmallFontSize,
|
||||
},
|
||||
active: {
|
||||
fontWeight: boldFont,
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
root: {
|
||||
|
@ -280,7 +284,6 @@ export default createMuiTheme({
|
|||
head: {
|
||||
letterSpacing: '1px',
|
||||
textTransform: 'uppercase',
|
||||
fontWeight: boldFont,
|
||||
},
|
||||
body: {
|
||||
color: primary,
|
||||
|
|