mirror of
https://github.com/status-im/liquid-funding.git
synced 2025-03-03 20:40:53 +00:00
feat: update to CRA with Embark
This commit is contained in:
parent
788a37c2f7
commit
5b48ad3d58
21
.eslintrc.js
21
.eslintrc.js
@ -69,7 +69,7 @@ module.exports = {
|
||||
"property"
|
||||
],
|
||||
"dot-notation": "off",
|
||||
"eol-last": "error",
|
||||
"eol-last": 1,
|
||||
"eqeqeq": "error",
|
||||
"for-direction": "error",
|
||||
"func-call-spacing": "error",
|
||||
@ -93,10 +93,7 @@ module.exports = {
|
||||
"jsx-quotes": "error",
|
||||
"key-spacing": "off",
|
||||
"keyword-spacing": "off",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"linebreak-style": 0,
|
||||
"line-comment-position": "off",
|
||||
"lines-around-comment": "error",
|
||||
"lines-around-directive": "error",
|
||||
@ -186,7 +183,7 @@ module.exports = {
|
||||
"no-restricted-properties": "error",
|
||||
"no-restricted-syntax": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-return-await": "error",
|
||||
"no-return-await": 1,
|
||||
"no-script-url": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
@ -244,19 +241,12 @@ module.exports = {
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "off",
|
||||
"prefer-template": "off",
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"quotes": 0,
|
||||
"quote-props": "off",
|
||||
"radix": "error",
|
||||
"require-await": "off",
|
||||
"require-jsdoc": "off",
|
||||
"rest-spread-spacing": "error",
|
||||
"semi": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"semi-spacing": [
|
||||
"error",
|
||||
{
|
||||
@ -310,6 +300,7 @@ module.exports = {
|
||||
"react/jsx-uses-vars": 1,
|
||||
"react/react-in-jsx-scope": 1,
|
||||
"react/prefer-es6-class": 1,
|
||||
"react/jsx-no-bind": 1
|
||||
"react/jsx-no-bind": 1,
|
||||
"react/prop-types": 1,
|
||||
}
|
||||
};
|
||||
|
24
.gitignore
vendored
24
.gitignore
vendored
@ -20,3 +20,27 @@ __pycache__
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
|
||||
|
||||
.embark
|
||||
chains.json
|
||||
config/production/password
|
||||
config/livenet/password
|
||||
config/development/devpassword
|
||||
config/development/password
|
||||
config/privatenet/password
|
||||
config/testnet/password
|
||||
coverage
|
||||
dist
|
||||
build/
|
||||
lib/
|
||||
node_modules/
|
||||
.DS_Store
|
||||
embarkArtifacts
|
||||
|
||||
.mypy_cache
|
||||
__pycache__
|
||||
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
|
@ -16,10 +16,15 @@ Welcome to the code for the liquid-funding dapp which uses the liquidpledging co
|
||||
|
||||
### Install
|
||||
1) `npm install`
|
||||
2) `npm -g install embark@4.0.0-alpha.2`
|
||||
2) `npm -g install embark`
|
||||
3) For development `embark run` or `embark run {network}`
|
||||
* There is an issue with the dev environment because of the contract size
|
||||
* Using `embark run rinkeby` works
|
||||
* You will need to either have a synced Geth node with Rinkeby (automatically started by Embark)
|
||||
* Add a `deployment` section to the contract config in `embarkConfig/contracts.js` ([example using Infura](https://embark.status.im/docs/contracts_deployment.html#Deploying-to-Infura))
|
||||
4) To start the CRA pipeline `npm run start`
|
||||
|
||||
### Requirements
|
||||
[NodeJS](https://nodejs.org/) (v8.4.0 or higher)
|
||||
[npm](https://www.npmjs.com/) (5.4.1 or higher)
|
||||
[Embark](https://embark.status.im/) (v4.0.0-alpha 2)
|
||||
[Embark](https://embark.status.im/) (v4.0.0 or higher)
|
||||
|
@ -1,227 +0,0 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { HashRouter as Router, Route, Link, Switch } from 'react-router-dom'
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Drawer from '@material-ui/core/Drawer'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import List from '@material-ui/core/List'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import MenuIcon from '@material-ui/icons/Menu'
|
||||
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'
|
||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight'
|
||||
import ListItem from '@material-ui/core/ListItem'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import ListItemText from '@material-ui/core/ListItemText'
|
||||
import InboxIcon from '@material-ui/icons/MoveToInbox'
|
||||
import { ScaleLoader } from 'react-spinners'
|
||||
import FundsManagement from './FundsManagement'
|
||||
import ContractAdmin from './ContractAdmin'
|
||||
import TransferGraph from './TransfersGraph'
|
||||
import Dashboard from './Dashboard'
|
||||
import Project from './projects/Project'
|
||||
import BackProject from './projects/BackProject'
|
||||
import CreateProject from './projects/CreateProject'
|
||||
import { FundingContext } from '../context'
|
||||
|
||||
const drawerWidth = 240
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
},
|
||||
appBar: {
|
||||
transition: theme.transitions.create(['margin', 'width'], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
},
|
||||
appBarShift: {
|
||||
width: `calc(100% - ${drawerWidth}px)`,
|
||||
marginLeft: drawerWidth,
|
||||
transition: theme.transitions.create(['margin', 'width'], {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
},
|
||||
appBarBg: {
|
||||
backgroundColor: '#111735'
|
||||
},
|
||||
menuButton: {
|
||||
marginLeft: 12,
|
||||
marginRight: 20,
|
||||
},
|
||||
hide: {
|
||||
display: 'none',
|
||||
},
|
||||
drawer: {
|
||||
width: drawerWidth,
|
||||
flexShrink: 0,
|
||||
},
|
||||
drawerPaper: {
|
||||
width: drawerWidth,
|
||||
},
|
||||
drawerHeader: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0 8px',
|
||||
...theme.mixins.toolbar,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
padding: theme.spacing.unit * 3,
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
marginLeft: -drawerWidth,
|
||||
},
|
||||
contentShift: {
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
marginLeft: 0,
|
||||
},
|
||||
link: {
|
||||
textDecoration: 'none'
|
||||
},
|
||||
networkButton: {
|
||||
color: '#ffeb3b'
|
||||
}
|
||||
})
|
||||
|
||||
function PersistentDrawerLeft({ classes, children, theme, loading }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const context = useContext(FundingContext)
|
||||
const { network, environment } = context
|
||||
const correctNetwork = network === environment
|
||||
|
||||
const handleDrawerOpen = () => {
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<CssBaseline />
|
||||
<AppBar
|
||||
position="fixed"
|
||||
className={classNames(classes.appBar, classes.appBarBg, {
|
||||
[classes.appBarShift]: open,
|
||||
})}
|
||||
>
|
||||
<Toolbar disableGutters={!open}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="Open drawer"
|
||||
onClick={handleDrawerOpen}
|
||||
className={classNames(classes.menuButton, open && !loading && classes.hide)}
|
||||
>
|
||||
{loading
|
||||
? <ScaleLoader
|
||||
sizeUnit={"px"}
|
||||
height={20}
|
||||
width={2}
|
||||
margin="3px"
|
||||
color={'#FFFFFF'}
|
||||
/>
|
||||
: <MenuIcon />}
|
||||
</IconButton>
|
||||
<Typography variant="h6" color="inherit" noWrap>
|
||||
Liquid Funding
|
||||
</Typography>
|
||||
<Button className={classes.networkButton}>
|
||||
{network && correctNetwork ? network : `Incorrect network`}
|
||||
</Button>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Drawer
|
||||
className={classes.drawer}
|
||||
variant="persistent"
|
||||
anchor="left"
|
||||
open={open}
|
||||
classes={{
|
||||
paper: classes.drawerPaper,
|
||||
}}
|
||||
>
|
||||
<div className={classes.drawerHeader}>
|
||||
<IconButton onClick={handleDrawerClose}>
|
||||
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
||||
</IconButton>
|
||||
</div>
|
||||
<Divider />
|
||||
<List>
|
||||
<Link to="/dashboard" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Dashboard" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/funds-management/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Funds Management" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/insights/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Insights" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/admin/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Admin" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<Divider />
|
||||
</Drawer>
|
||||
<main
|
||||
className={classNames(classes.content, {
|
||||
[classes.contentShift]: open,
|
||||
})}
|
||||
>
|
||||
<div className={classes.drawerHeader} />
|
||||
<div className={classNames(classes.appBar)}>
|
||||
<Switch>
|
||||
<Route path="/(|dashboard)" component={Dashboard} />
|
||||
<Route path="/admin" component={ContractAdmin} />
|
||||
<Route path="/funds-management" render={() => <FundsManagement open={open} />} />
|
||||
<Route path="/insights" component={TransferGraph} />
|
||||
<Route path="/project/:id" component={Project} />
|
||||
<Route path="/create-project/" render={(props) => <CreateProject {...props} />} />
|
||||
<Route path="/back-project/:id" component={BackProject} />
|
||||
</Switch>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
PersistentDrawerLeft.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
children: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
loading: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default withStyles(styles, { withTheme: true })(PersistentDrawerLeft)
|
@ -1,131 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import withObservables from '@nozbe/with-observables'
|
||||
import { Q } from '@nozbe/watermelondb'
|
||||
import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import LinearProgress from '@material-ui/core/LinearProgress'
|
||||
import { getDepositWithdrawTotals, getPledgesWaitingCommit } from '../../selectors/pledging'
|
||||
import { getTokenAddress } from '../../utils/currencies'
|
||||
|
||||
const styles = {
|
||||
card: {
|
||||
minWidth: 275,
|
||||
},
|
||||
cardTitle: {
|
||||
paddingBottom: '1rem'
|
||||
},
|
||||
fundingSummaries: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center'
|
||||
},
|
||||
bullet: {
|
||||
display: 'inline-block',
|
||||
margin: '0 2px',
|
||||
transform: 'scale(0.8)',
|
||||
},
|
||||
title: {
|
||||
fontSize: 14,
|
||||
},
|
||||
pos: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
linearColorPrimary: {
|
||||
backgroundColor: '#b2dfdb',
|
||||
},
|
||||
linearBarColorPrimary: {
|
||||
backgroundColor: '#00695c',
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'center',
|
||||
paddingTop: '2rem'
|
||||
}
|
||||
}
|
||||
|
||||
const getNet = (deposits, withdraws) => Number(deposits) - Number(withdraws)
|
||||
const getValue = (deposits, withdraws) => (getNet(deposits, withdraws) / Number(deposits)) * 100
|
||||
function SimpleCard(props) {
|
||||
const { classes, title, transfers, pledges, vaultEvents } = props
|
||||
|
||||
return (
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography variant="h5" className={classes.cardTitle}>
|
||||
{title}
|
||||
</Typography>
|
||||
{!!transfers && !!pledges.length &&
|
||||
Object.entries(getDepositWithdrawTotals({ transfers, pledges, vaultEvents }))
|
||||
.map(token => {
|
||||
const [name, amounts] = token
|
||||
const { deposits, withdraws } = amounts
|
||||
const address = getTokenAddress(name)
|
||||
const pledgesForCommit = getPledgesWaitingCommit({ pledges }).filter(p => p.token == address)
|
||||
return (
|
||||
<Card key={name}>
|
||||
<Typography variant="h5" className={classes.titleText}>
|
||||
{name}
|
||||
</Typography>
|
||||
<CardContent className={classes.fundingSummaries}>
|
||||
<Typography variant="h3">
|
||||
{Number(deposits) - Number(withdraws || 0)}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'total'} className={classes.pos} color="textSecondary">
|
||||
Remaining In Pledges
|
||||
</Typography>
|
||||
<Typography variant="h3" >
|
||||
{deposits}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'withdraw'} className={classes.pos} color="textSecondary">
|
||||
Funded
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
{withdraws || 0}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'deposit'} className={classes.pos} color="textSecondary">
|
||||
Withdrawn
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
{pledgesForCommit.length}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'veto/approve'} className={classes.pos} color="textSecondary">
|
||||
Pledges that can be vetoed / approved
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<LinearProgress
|
||||
classes={{
|
||||
colorPrimary: classes.linearColorPrimary,
|
||||
barColorPrimary: classes.linearBarColorPrimary,
|
||||
}}
|
||||
color="primary"
|
||||
variant="buffer"
|
||||
value={getValue(deposits, withdraws)}
|
||||
valueBuffer={100}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
SimpleCard.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
title: PropTypes.string,
|
||||
pledges: PropTypes.array.isRequired,
|
||||
transfers: PropTypes.array.isRequired,
|
||||
vaultEvents: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
const styledCard = withStyles(styles)(SimpleCard)
|
||||
export default withDatabase(withObservables([], ({ database }) => ({
|
||||
transfers: database.collections.get('lp_events').query(
|
||||
Q.where('event', 'Transfer')
|
||||
).observe(),
|
||||
vaultEvents : database.collections.get('vault_events').query().observe()
|
||||
}))(styledCard))
|
||||
|
@ -1,21 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
const docType = doc => {
|
||||
const suffix = doc.name.split('.')
|
||||
return suffix.slice(-1)[0]
|
||||
}
|
||||
|
||||
export default ({ status }) => {
|
||||
return (
|
||||
<div>
|
||||
{status && status.profileImg &&
|
||||
<div>
|
||||
{['jpg', 'gif', 'png'].includes(docType(status.profileImg)) &&
|
||||
<img src={status.profileImg.img} alt='ipfs' style={{ maxWidth: '90%' }} />}
|
||||
{docType(status.profileImg) === 'pdf' &&
|
||||
<iframe src={status.profileImg.img} style={{ width: '100%', height: '90%' }}/>}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Status.im Liquid Funding</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" />
|
||||
</head>
|
||||
<body class="container">
|
||||
<div id="app">
|
||||
</div>
|
||||
<script src="js/index.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,307 +0,0 @@
|
||||
// examples: https://nagix.github.io/chartjs-plugin-colorschemes/
|
||||
export const colors = {
|
||||
// Sequential
|
||||
YlGn3: ['#f7fcb9', '#addd8e', '#31a354'],
|
||||
YlGn4: ['#ffffcc', '#c2e699', '#78c679', '#238443'],
|
||||
YlGn5: ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'],
|
||||
YlGn6: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#31a354', '#006837'],
|
||||
YlGn7: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'],
|
||||
YlGn8: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'],
|
||||
YlGn9: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'],
|
||||
|
||||
YlGnBu3: ['#edf8b1', '#7fcdbb', '#2c7fb8'],
|
||||
YlGnBu4: ['#ffffcc', '#a1dab4', '#41b6c4', '#225ea8'],
|
||||
YlGnBu5: ['#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494'],
|
||||
YlGnBu6: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#2c7fb8', '#253494'],
|
||||
YlGnBu7: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'],
|
||||
YlGnBu8: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'],
|
||||
YlGnBu9: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'],
|
||||
|
||||
GnBu3: ['#e0f3db', '#a8ddb5', '#43a2ca'],
|
||||
GnBu4: ['#f0f9e8', '#bae4bc', '#7bccc4', '#2b8cbe'],
|
||||
GnBu5: ['#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac'],
|
||||
GnBu6: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#43a2ca', '#0868ac'],
|
||||
GnBu7: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'],
|
||||
GnBu8: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'],
|
||||
GnBu9: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'],
|
||||
|
||||
BuGn3: ['#e5f5f9', '#99d8c9', '#2ca25f'],
|
||||
BuGn4: ['#edf8fb', '#b2e2e2', '#66c2a4', '#238b45'],
|
||||
BuGn5: ['#edf8fb', '#b2e2e2', '#66c2a4', '#2ca25f', '#006d2c'],
|
||||
BuGn6: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#2ca25f', '#006d2c'],
|
||||
BuGn7: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'],
|
||||
BuGn8: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'],
|
||||
BuGn9: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'],
|
||||
|
||||
PuBuGn3: ['#ece2f0', '#a6bddb', '#1c9099'],
|
||||
PuBuGn4: ['#f6eff7', '#bdc9e1', '#67a9cf', '#02818a'],
|
||||
PuBuGn5: ['#f6eff7', '#bdc9e1', '#67a9cf', '#1c9099', '#016c59'],
|
||||
PuBuGn6: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#1c9099', '#016c59'],
|
||||
PuBuGn7: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'],
|
||||
PuBuGn8: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'],
|
||||
PuBuGn9: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'],
|
||||
|
||||
PuBu3: ['#ece7f2', '#a6bddb', '#2b8cbe'],
|
||||
PuBu4: ['#f1eef6', '#bdc9e1', '#74a9cf', '#0570b0'],
|
||||
PuBu5: ['#f1eef6', '#bdc9e1', '#74a9cf', '#2b8cbe', '#045a8d'],
|
||||
PuBu6: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#2b8cbe', '#045a8d'],
|
||||
PuBu7: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'],
|
||||
PuBu8: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'],
|
||||
PuBu9: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'],
|
||||
|
||||
BuPu3: ['#e0ecf4', '#9ebcda', '#8856a7'],
|
||||
BuPu4: ['#edf8fb', '#b3cde3', '#8c96c6', '#88419d'],
|
||||
BuPu5: ['#edf8fb', '#b3cde3', '#8c96c6', '#8856a7', '#810f7c'],
|
||||
BuPu6: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8856a7', '#810f7c'],
|
||||
BuPu7: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'],
|
||||
BuPu8: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'],
|
||||
BuPu9: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'],
|
||||
|
||||
RdPu3: ['#fde0dd', '#fa9fb5', '#c51b8a'],
|
||||
RdPu4: ['#feebe2', '#fbb4b9', '#f768a1', '#ae017e'],
|
||||
RdPu5: ['#feebe2', '#fbb4b9', '#f768a1', '#c51b8a', '#7a0177'],
|
||||
RdPu6: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#c51b8a', '#7a0177'],
|
||||
RdPu7: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'],
|
||||
RdPu8: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'],
|
||||
RdPu9: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'],
|
||||
|
||||
PuRd3: ['#e7e1ef', '#c994c7', '#dd1c77'],
|
||||
PuRd4: ['#f1eef6', '#d7b5d8', '#df65b0', '#ce1256'],
|
||||
PuRd5: ['#f1eef6', '#d7b5d8', '#df65b0', '#dd1c77', '#980043'],
|
||||
PuRd6: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#dd1c77', '#980043'],
|
||||
PuRd7: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'],
|
||||
PuRd8: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'],
|
||||
PuRd9: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'],
|
||||
|
||||
OrRd3: ['#fee8c8', '#fdbb84', '#e34a33'],
|
||||
OrRd4: ['#fef0d9', '#fdcc8a', '#fc8d59', '#d7301f'],
|
||||
OrRd5: ['#fef0d9', '#fdcc8a', '#fc8d59', '#e34a33', '#b30000'],
|
||||
OrRd6: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#e34a33', '#b30000'],
|
||||
OrRd7: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'],
|
||||
OrRd8: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'],
|
||||
OrRd9: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],
|
||||
|
||||
YlOrRd3: ['#ffeda0', '#feb24c', '#f03b20'],
|
||||
YlOrRd4: ['#ffffb2', '#fecc5c', '#fd8d3c', '#e31a1c'],
|
||||
YlOrRd5: ['#ffffb2', '#fecc5c', '#fd8d3c', '#f03b20', '#bd0026'],
|
||||
YlOrRd6: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'],
|
||||
YlOrRd7: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'],
|
||||
YlOrRd8: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'],
|
||||
YlOrRd9: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],
|
||||
|
||||
YlOrBr3: ['#fff7bc', '#fec44f', '#d95f0e'],
|
||||
YlOrBr4: ['#ffffd4', '#fed98e', '#fe9929', '#cc4c02'],
|
||||
YlOrBr5: ['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'],
|
||||
YlOrBr6: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#d95f0e', '#993404'],
|
||||
YlOrBr7: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'],
|
||||
YlOrBr8: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'],
|
||||
YlOrBr9: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'],
|
||||
|
||||
Purples3: ['#efedf5', '#bcbddc', '#756bb1'],
|
||||
Purples4: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#6a51a3'],
|
||||
Purples5: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#756bb1', '#54278f'],
|
||||
Purples6: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f'],
|
||||
Purples7: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'],
|
||||
Purples8: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'],
|
||||
Purples9: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'],
|
||||
|
||||
Blues3: ['#deebf7', '#9ecae1', '#3182bd'],
|
||||
Blues4: ['#eff3ff', '#bdd7e7', '#6baed6', '#2171b5'],
|
||||
Blues5: ['#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'],
|
||||
Blues6: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#3182bd', '#08519c'],
|
||||
Blues7: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
|
||||
Blues8: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
|
||||
Blues9: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'],
|
||||
|
||||
Greens3: ['#e5f5e0', '#a1d99b', '#31a354'],
|
||||
Greens4: ['#edf8e9', '#bae4b3', '#74c476', '#238b45'],
|
||||
Greens5: ['#edf8e9', '#bae4b3', '#74c476', '#31a354', '#006d2c'],
|
||||
Greens6: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#31a354', '#006d2c'],
|
||||
Greens7: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'],
|
||||
Greens8: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'],
|
||||
Greens9: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'],
|
||||
|
||||
Oranges3: ['#fee6ce', '#fdae6b', '#e6550d'],
|
||||
Oranges4: ['#feedde', '#fdbe85', '#fd8d3c', '#d94701'],
|
||||
Oranges5: ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603'],
|
||||
Oranges6: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#e6550d', '#a63603'],
|
||||
Oranges7: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'],
|
||||
Oranges8: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'],
|
||||
Oranges9: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'],
|
||||
|
||||
Reds3: ['#fee0d2', '#fc9272', '#de2d26'],
|
||||
Reds4: ['#fee5d9', '#fcae91', '#fb6a4a', '#cb181d'],
|
||||
Reds5: ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15'],
|
||||
Reds6: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#de2d26', '#a50f15'],
|
||||
Reds7: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'],
|
||||
Reds8: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'],
|
||||
Reds9: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'],
|
||||
|
||||
Greys3: ['#f0f0f0', '#bdbdbd', '#636363'],
|
||||
Greys4: ['#f7f7f7', '#cccccc', '#969696', '#525252'],
|
||||
Greys5: ['#f7f7f7', '#cccccc', '#969696', '#636363', '#252525'],
|
||||
Greys6: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#636363', '#252525'],
|
||||
Greys7: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'],
|
||||
Greys8: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'],
|
||||
Greys9: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'],
|
||||
|
||||
// Diverging
|
||||
PuOr3: ['#f1a340', '#f7f7f7', '#998ec3'],
|
||||
PuOr4: ['#e66101', '#fdb863', '#b2abd2', '#5e3c99'],
|
||||
PuOr5: ['#e66101', '#fdb863', '#f7f7f7', '#b2abd2', '#5e3c99'],
|
||||
PuOr6: ['#b35806', '#f1a340', '#fee0b6', '#d8daeb', '#998ec3', '#542788'],
|
||||
PuOr7: ['#b35806', '#f1a340', '#fee0b6', '#f7f7f7', '#d8daeb', '#998ec3', '#542788'],
|
||||
PuOr8: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788'],
|
||||
PuOr9: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788'],
|
||||
PuOr10: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],
|
||||
PuOr11: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],
|
||||
|
||||
BrBG3: ['#d8b365', '#f5f5f5', '#5ab4ac'],
|
||||
BrBG4: ['#a6611a', '#dfc27d', '#80cdc1', '#018571'],
|
||||
BrBG5: ['#a6611a', '#dfc27d', '#f5f5f5', '#80cdc1', '#018571'],
|
||||
BrBG6: ['#8c510a', '#d8b365', '#f6e8c3', '#c7eae5', '#5ab4ac', '#01665e'],
|
||||
BrBG7: ['#8c510a', '#d8b365', '#f6e8c3', '#f5f5f5', '#c7eae5', '#5ab4ac', '#01665e'],
|
||||
BrBG8: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e'],
|
||||
BrBG9: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e'],
|
||||
BrBG10: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],
|
||||
BrBG11: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],
|
||||
|
||||
PRGn3: ['#af8dc3', '#f7f7f7', '#7fbf7b'],
|
||||
PRGn4: ['#7b3294', '#c2a5cf', '#a6dba0', '#008837'],
|
||||
PRGn5: ['#7b3294', '#c2a5cf', '#f7f7f7', '#a6dba0', '#008837'],
|
||||
PRGn6: ['#762a83', '#af8dc3', '#e7d4e8', '#d9f0d3', '#7fbf7b', '#1b7837'],
|
||||
PRGn7: ['#762a83', '#af8dc3', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#7fbf7b', '#1b7837'],
|
||||
PRGn8: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'],
|
||||
PRGn9: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'],
|
||||
PRGn10: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],
|
||||
PRGn11: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],
|
||||
|
||||
PiYG3: ['#e9a3c9', '#f7f7f7', '#a1d76a'],
|
||||
PiYG4: ['#d01c8b', '#f1b6da', '#b8e186', '#4dac26'],
|
||||
PiYG5: ['#d01c8b', '#f1b6da', '#f7f7f7', '#b8e186', '#4dac26'],
|
||||
PiYG6: ['#c51b7d', '#e9a3c9', '#fde0ef', '#e6f5d0', '#a1d76a', '#4d9221'],
|
||||
PiYG7: ['#c51b7d', '#e9a3c9', '#fde0ef', '#f7f7f7', '#e6f5d0', '#a1d76a', '#4d9221'],
|
||||
PiYG8: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'],
|
||||
PiYG9: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'],
|
||||
PiYG10: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],
|
||||
PiYG11: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],
|
||||
|
||||
RdBu3: ['#ef8a62', '#f7f7f7', '#67a9cf'],
|
||||
RdBu4: ['#ca0020', '#f4a582', '#92c5de', '#0571b0'],
|
||||
RdBu5: ['#ca0020', '#f4a582', '#f7f7f7', '#92c5de', '#0571b0'],
|
||||
RdBu6: ['#b2182b', '#ef8a62', '#fddbc7', '#d1e5f0', '#67a9cf', '#2166ac'],
|
||||
RdBu7: ['#b2182b', '#ef8a62', '#fddbc7', '#f7f7f7', '#d1e5f0', '#67a9cf', '#2166ac'],
|
||||
RdBu8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'],
|
||||
RdBu9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'],
|
||||
RdBu10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],
|
||||
RdBu11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],
|
||||
|
||||
RdGy3: ['#ef8a62', '#ffffff', '#999999'],
|
||||
RdGy4: ['#ca0020', '#f4a582', '#bababa', '#404040'],
|
||||
RdGy5: ['#ca0020', '#f4a582', '#ffffff', '#bababa', '#404040'],
|
||||
RdGy6: ['#b2182b', '#ef8a62', '#fddbc7', '#e0e0e0', '#999999', '#4d4d4d'],
|
||||
RdGy7: ['#b2182b', '#ef8a62', '#fddbc7', '#ffffff', '#e0e0e0', '#999999', '#4d4d4d'],
|
||||
RdGy8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'],
|
||||
RdGy9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'],
|
||||
RdGy10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],
|
||||
RdGy11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],
|
||||
|
||||
RdYlBu3: ['#fc8d59', '#ffffbf', '#91bfdb'],
|
||||
RdYlBu4: ['#d7191c', '#fdae61', '#abd9e9', '#2c7bb6'],
|
||||
RdYlBu5: ['#d7191c', '#fdae61', '#ffffbf', '#abd9e9', '#2c7bb6'],
|
||||
RdYlBu6: ['#d73027', '#fc8d59', '#fee090', '#e0f3f8', '#91bfdb', '#4575b4'],
|
||||
RdYlBu7: ['#d73027', '#fc8d59', '#fee090', '#ffffbf', '#e0f3f8', '#91bfdb', '#4575b4'],
|
||||
RdYlBu8: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'],
|
||||
RdYlBu9: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'],
|
||||
RdYlBu10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],
|
||||
RdYlBu11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],
|
||||
|
||||
Spectral3: ['#fc8d59', '#ffffbf', '#99d594'],
|
||||
Spectral4: ['#d7191c', '#fdae61', '#abdda4', '#2b83ba'],
|
||||
Spectral5: ['#d7191c', '#fdae61', '#ffffbf', '#abdda4', '#2b83ba'],
|
||||
Spectral6: ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd'],
|
||||
Spectral7: ['#d53e4f', '#fc8d59', '#fee08b', '#ffffbf', '#e6f598', '#99d594', '#3288bd'],
|
||||
Spectral8: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'],
|
||||
Spectral9: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'],
|
||||
Spectral10: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],
|
||||
Spectral11: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],
|
||||
|
||||
RdYlGn3: ['#fc8d59', '#ffffbf', '#91cf60'],
|
||||
RdYlGn4: ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'],
|
||||
RdYlGn5: ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641'],
|
||||
RdYlGn6: ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'],
|
||||
RdYlGn7: ['#d73027', '#fc8d59', '#fee08b', '#ffffbf', '#d9ef8b', '#91cf60', '#1a9850'],
|
||||
RdYlGn8: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'],
|
||||
RdYlGn9: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'],
|
||||
RdYlGn10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],
|
||||
RdYlGn11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],
|
||||
|
||||
// Qualitative
|
||||
Accent3: ['#7fc97f', '#beaed4', '#fdc086'],
|
||||
Accent4: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99'],
|
||||
Accent5: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0'],
|
||||
Accent6: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'],
|
||||
Accent7: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17'],
|
||||
Accent8: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'],
|
||||
|
||||
'Dark2-3': ['#1b9e77', '#d95f02', '#7570b3'],
|
||||
'Dark2-4': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a'],
|
||||
'Dark2-5': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e'],
|
||||
'Dark2-6': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02'],
|
||||
'Dark2-7': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d'],
|
||||
'Dark2-8': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'],
|
||||
|
||||
Paired3: ['#a6cee3', '#1f78b4', '#b2df8a'],
|
||||
Paired4: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c'],
|
||||
Paired5: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99'],
|
||||
Paired6: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c'],
|
||||
Paired7: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f'],
|
||||
Paired8: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00'],
|
||||
Paired9: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6'],
|
||||
Paired10: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a'],
|
||||
Paired11: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99'],
|
||||
Paired12: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'],
|
||||
|
||||
'Pastel1-3': ['#fbb4ae', '#b3cde3', '#ccebc5'],
|
||||
'Pastel1-4': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4'],
|
||||
'Pastel1-5': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6'],
|
||||
'Pastel1-6': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc'],
|
||||
'Pastel1-7': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd'],
|
||||
'Pastel1-8': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec'],
|
||||
'Pastel1-9': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'],
|
||||
|
||||
'Pastel2-3': ['#b3e2cd', '#fdcdac', '#cbd5e8'],
|
||||
'Pastel2-4': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4'],
|
||||
'Pastel2-5': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9'],
|
||||
'Pastel2-6': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae'],
|
||||
'Pastel2-7': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc'],
|
||||
'Pastel2-8': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'],
|
||||
|
||||
'Set1-3': ['#e41a1c', '#377eb8', '#4daf4a'],
|
||||
'Set1-4': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3'],
|
||||
'Set1-5': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'],
|
||||
'Set1-6': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33'],
|
||||
'Set1-7': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628'],
|
||||
'Set1-8': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf'],
|
||||
'Set1-9': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'],
|
||||
|
||||
'Set2-3': ['#66c2a5', '#fc8d62', '#8da0cb'],
|
||||
'Set2-4': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3'],
|
||||
'Set2-5': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854'],
|
||||
'Set2-6': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f'],
|
||||
'Set2-7': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494'],
|
||||
'Set2-8': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'],
|
||||
|
||||
'Set3-3': ['#8dd3c7', '#ffffb3', '#bebada'],
|
||||
'Set3-4': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072'],
|
||||
'Set3-5': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'],
|
||||
'Set3-6': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462'],
|
||||
'Set3-7': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69'],
|
||||
'Set3-8': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5'],
|
||||
'Set3-9': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9'],
|
||||
'Set3-10': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd'],
|
||||
'Set3-11': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5'],
|
||||
'Set3-12': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f']
|
||||
};
|
||||
|
||||
export const getColor = (pallet, idx) => colors[pallet][idx % colors[pallet].length]
|
@ -1,21 +0,0 @@
|
||||
export function timeSinceBlock(date, interval) {
|
||||
var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7;
|
||||
let date1 = new Date(date*1000);
|
||||
let date2 = new Date();
|
||||
var timediff = date2 - date1;
|
||||
if (isNaN(timediff)) return NaN;
|
||||
switch (interval) {
|
||||
case "years": return date2.getFullYear() - date1.getFullYear();
|
||||
case "months": return (
|
||||
( date2.getFullYear() * 12 + date2.getMonth() )
|
||||
-
|
||||
( date1.getFullYear() * 12 + date1.getMonth() )
|
||||
);
|
||||
case "weeks" : return Math.floor(timediff / week)
|
||||
case "days" : return Math.floor(timediff / day)
|
||||
case "hours" : return Math.floor(timediff / hour)
|
||||
case "minutes": return Math.floor(timediff / minute)
|
||||
case "seconds": return Math.floor(timediff / second)
|
||||
default: return undefined
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* This source code was adapted from:
|
||||
* https://github.com/facebook/create-react-app/blob/v2.0.4/packages/babel-preset-react-app/webpack-overrides.js
|
||||
*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* The MIT license for this code may be found on GitHub:
|
||||
* https://github.com/facebook/create-react-app/blob/v2.0.4/packages/babel-preset-react-app/LICENSE
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
const macroCheck = new RegExp('[./]macro');
|
||||
|
||||
module.exports = function () {
|
||||
return {
|
||||
config(config, {source}) {
|
||||
// don't cache babel macros
|
||||
// https://github.com/babel/babel/issues/8497
|
||||
if (macroCheck.test(source)) {
|
||||
return Object.assign({}, config.options, {
|
||||
caller: Object.assign({}, config.options.caller, {
|
||||
macroInvalidationToken: crypto.randomBytes(32).toString('hex')
|
||||
})
|
||||
});
|
||||
}
|
||||
return config.options;
|
||||
}
|
||||
};
|
||||
};
|
93
config/env.js
Normal file
93
config/env.js
Normal file
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const paths = require('./paths');
|
||||
|
||||
// Make sure that including paths.js after env.js will read .env variables.
|
||||
delete require.cache[require.resolve('./paths')];
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
if (!NODE_ENV) {
|
||||
throw new Error(
|
||||
'The NODE_ENV environment variable is required but was not specified.'
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
|
||||
var dotenvFiles = [
|
||||
`${paths.dotenv}.${NODE_ENV}.local`,
|
||||
`${paths.dotenv}.${NODE_ENV}`,
|
||||
// Don't include `.env.local` for `test` environment
|
||||
// since normally you expect tests to produce the same
|
||||
// results for everyone
|
||||
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
|
||||
paths.dotenv,
|
||||
].filter(Boolean);
|
||||
|
||||
// Load environment variables from .env* files. Suppress warnings using silent
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set. Variable expansion is supported in .env files.
|
||||
// https://github.com/motdotla/dotenv
|
||||
// https://github.com/motdotla/dotenv-expand
|
||||
dotenvFiles.forEach(dotenvFile => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
require('dotenv-expand')(
|
||||
require('dotenv').config({
|
||||
path: dotenvFile,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// We support resolving modules according to `NODE_PATH`.
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
// https://github.com/facebook/create-react-app/issues/253.
|
||||
// It works similar to `NODE_PATH` in Node itself:
|
||||
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
|
||||
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
|
||||
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
|
||||
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
|
||||
// We also resolve them to make sure all tools using them work consistently.
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||
.split(path.delimiter)
|
||||
.filter(folder => folder && !path.isAbsolute(folder))
|
||||
.map(folder => path.resolve(appDirectory, folder))
|
||||
.join(path.delimiter);
|
||||
|
||||
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
|
||||
// injected into the application via DefinePlugin in Webpack configuration.
|
||||
const REACT_APP = /^REACT_APP_/i;
|
||||
|
||||
function getClientEnvironment(publicUrl) {
|
||||
const raw = Object.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce(
|
||||
(env, key) => {
|
||||
env[key] = process.env[key];
|
||||
return env;
|
||||
},
|
||||
{
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
PUBLIC_URL: publicUrl,
|
||||
}
|
||||
);
|
||||
// Stringify all values so we can feed into Webpack DefinePlugin
|
||||
const stringified = {
|
||||
'process.env': Object.keys(raw).reduce((env, key) => {
|
||||
env[key] = JSON.stringify(raw[key]);
|
||||
return env;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
return { raw, stringified };
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
14
config/jest/cssTransform.js
Normal file
14
config/jest/cssTransform.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
// This is a custom Jest transformer turning style imports into empty objects.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process() {
|
||||
return 'module.exports = {};';
|
||||
},
|
||||
getCacheKey() {
|
||||
// The output is always the same.
|
||||
return 'cssTransform';
|
||||
},
|
||||
};
|
31
config/jest/fileTransform.js
Normal file
31
config/jest/fileTransform.js
Normal file
@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// This is a custom Jest transformer turning file imports into filenames.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process(src, filename) {
|
||||
const assetFilename = JSON.stringify(path.basename(filename));
|
||||
|
||||
if (filename.match(/\.svg$/)) {
|
||||
return `const React = require('react');
|
||||
module.exports = {
|
||||
__esModule: true,
|
||||
default: ${assetFilename},
|
||||
ReactComponent: React.forwardRef((props, ref) => ({
|
||||
$$typeof: Symbol.for('react.element'),
|
||||
type: 'svg',
|
||||
ref: ref,
|
||||
key: null,
|
||||
props: Object.assign({}, props, {
|
||||
children: ${assetFilename}
|
||||
})
|
||||
})),
|
||||
};`;
|
||||
}
|
||||
|
||||
return `module.exports = ${assetFilename};`;
|
||||
},
|
||||
};
|
89
config/paths.js
Normal file
89
config/paths.js
Normal file
@ -0,0 +1,89 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const url = require('url');
|
||||
|
||||
// Make sure any symlinks in the project folder are resolved:
|
||||
// https://github.com/facebook/create-react-app/issues/637
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
||||
|
||||
const envPublicUrl = process.env.PUBLIC_URL;
|
||||
|
||||
function ensureSlash(inputPath, needsSlash) {
|
||||
const hasSlash = inputPath.endsWith('/');
|
||||
if (hasSlash && !needsSlash) {
|
||||
return inputPath.substr(0, inputPath.length - 1);
|
||||
} else if (!hasSlash && needsSlash) {
|
||||
return `${inputPath}/`;
|
||||
} else {
|
||||
return inputPath;
|
||||
}
|
||||
}
|
||||
|
||||
const getPublicUrl = appPackageJson =>
|
||||
envPublicUrl || require(appPackageJson).homepage;
|
||||
|
||||
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
|
||||
// "public path" at which the app is served.
|
||||
// Webpack needs to know it to put the right <script> hrefs into HTML even in
|
||||
// single-page apps that may serve index.html for nested URLs like /todos/42.
|
||||
// We can't use a relative path in HTML because we don't want to load something
|
||||
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
|
||||
function getServedPath(appPackageJson) {
|
||||
const publicUrl = getPublicUrl(appPackageJson);
|
||||
const servedUrl =
|
||||
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
|
||||
return ensureSlash(servedUrl, true);
|
||||
}
|
||||
|
||||
const moduleFileExtensions = [
|
||||
'web.mjs',
|
||||
'mjs',
|
||||
'web.js',
|
||||
'js',
|
||||
'web.ts',
|
||||
'ts',
|
||||
'web.tsx',
|
||||
'tsx',
|
||||
'json',
|
||||
'web.jsx',
|
||||
'jsx',
|
||||
];
|
||||
|
||||
// Resolve file paths in the same order as webpack
|
||||
const resolveModule = (resolveFn, filePath) => {
|
||||
const extension = moduleFileExtensions.find(extension =>
|
||||
fs.existsSync(resolveFn(`${filePath}.${extension}`))
|
||||
);
|
||||
|
||||
if (extension) {
|
||||
return resolveFn(`${filePath}.${extension}`);
|
||||
}
|
||||
|
||||
return resolveFn(`${filePath}.js`);
|
||||
};
|
||||
|
||||
// config after eject: we're in ./config/
|
||||
module.exports = {
|
||||
dotenv: resolveApp('.env'),
|
||||
appPath: resolveApp('.'),
|
||||
appBuild: resolveApp('build'),
|
||||
appPublic: resolveApp('public'),
|
||||
appHtml: resolveApp('public/index.html'),
|
||||
appIndexJs: resolveModule(resolveApp, 'src/index'),
|
||||
appPackageJson: resolveApp('package.json'),
|
||||
appSrc: resolveApp('src'),
|
||||
appTsConfig: resolveApp('tsconfig.json'),
|
||||
yarnLockFile: resolveApp('yarn.lock'),
|
||||
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
|
||||
proxySetup: resolveApp('src/setupProxy.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
publicUrl: getPublicUrl(resolveApp('package.json')),
|
||||
servedPath: getServedPath(resolveApp('package.json')),
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports.moduleFileExtensions = moduleFileExtensions;
|
610
config/webpack.config.js
Normal file
610
config/webpack.config.js
Normal file
@ -0,0 +1,610 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const resolve = require('resolve');
|
||||
const PnpWebpackPlugin = require('pnp-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const safePostCssParser = require('postcss-safe-parser');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
||||
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
const paths = require('./paths');
|
||||
const getClientEnvironment = require('./env');
|
||||
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
|
||||
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
||||
|
||||
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
|
||||
// makes for a smoother build process.
|
||||
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
||||
|
||||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
const sassRegex = /\.(scss|sass)$/;
|
||||
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
|
||||
// This is the production and development configuration.
|
||||
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
|
||||
module.exports = function(webpackEnv) {
|
||||
const isEnvDevelopment = webpackEnv === 'development';
|
||||
const isEnvProduction = webpackEnv === 'production';
|
||||
|
||||
// Webpack uses `publicPath` to determine where the app is being served from.
|
||||
// It requires a trailing slash, or the file assets will get an incorrect path.
|
||||
// In development, we always serve from the root. This makes config easier.
|
||||
const publicPath = isEnvProduction
|
||||
? paths.servedPath
|
||||
: isEnvDevelopment && '/';
|
||||
// Some apps do not use client-side routing with pushState.
|
||||
// For these, "homepage" can be set to "." to enable relative asset paths.
|
||||
const shouldUseRelativeAssetPaths = publicPath === './';
|
||||
|
||||
// `publicUrl` is just like `publicPath`, but we will provide it to our app
|
||||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
|
||||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
|
||||
const publicUrl = isEnvProduction
|
||||
? publicPath.slice(0, -1)
|
||||
: isEnvDevelopment && '';
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
isEnvDevelopment && require.resolve('style-loader'),
|
||||
isEnvProduction && {
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: Object.assign(
|
||||
{},
|
||||
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
|
||||
),
|
||||
},
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
],
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
].filter(Boolean);
|
||||
if (preProcessor) {
|
||||
loaders.push({
|
||||
loader: require.resolve(preProcessor),
|
||||
options: {
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
});
|
||||
}
|
||||
return loaders;
|
||||
};
|
||||
|
||||
return {
|
||||
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
|
||||
// Stop compilation early in production
|
||||
bail: isEnvProduction,
|
||||
devtool: isEnvProduction
|
||||
? shouldUseSourceMap
|
||||
? 'source-map'
|
||||
: false
|
||||
: isEnvDevelopment && 'cheap-module-source-map',
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
entry: [
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
isEnvDevelopment &&
|
||||
require.resolve('react-dev-utils/webpackHotDevClient'),
|
||||
// Finally, this is your app's code:
|
||||
paths.appIndexJs,
|
||||
// We include the app code last so that if there is a runtime error during
|
||||
// initialization, it doesn't blow up the WebpackDevServer client, and
|
||||
// changing JS code would still trigger a refresh.
|
||||
].filter(Boolean),
|
||||
output: {
|
||||
// The build folder.
|
||||
path: isEnvProduction ? paths.appBuild : undefined,
|
||||
// Add /* filename */ comments to generated require()s in the output.
|
||||
pathinfo: isEnvDevelopment,
|
||||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// In development, it does not produce real files.
|
||||
filename: isEnvProduction
|
||||
? 'static/js/[name].[contenthash:8].js'
|
||||
: isEnvDevelopment && 'static/js/bundle.js',
|
||||
// There are also additional JS chunk files if you use code splitting.
|
||||
chunkFilename: isEnvProduction
|
||||
? 'static/js/[name].[contenthash:8].chunk.js'
|
||||
: isEnvDevelopment && 'static/js/[name].chunk.js',
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
// We use "/" in development.
|
||||
publicPath: publicPath,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: isEnvProduction
|
||||
? info =>
|
||||
path
|
||||
.relative(paths.appSrc, info.absoluteResourcePath)
|
||||
.replace(/\\/g, '/')
|
||||
: isEnvDevelopment &&
|
||||
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
|
||||
globalObject: 'this',
|
||||
},
|
||||
optimization: {
|
||||
minimize: isEnvProduction,
|
||||
minimizer: [
|
||||
// This is only used in production mode
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
parse: {
|
||||
// we want terser to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minfication steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
// Disabled because of an issue with Terser breaking valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/5250
|
||||
// Pending futher investigation:
|
||||
// https://github.com/terser-js/terser/issues/120
|
||||
inline: 2,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
// Use multi-process parallel running to improve the build speed
|
||||
// Default number of concurrent runs: os.cpus().length - 1
|
||||
parallel: true,
|
||||
// Enable file caching
|
||||
cache: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// This is only used in production mode
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessorOptions: {
|
||||
parser: safePostCssParser,
|
||||
map: shouldUseSourceMap
|
||||
? {
|
||||
// `inline: false` forces the sourcemap to be output into a
|
||||
// separate file
|
||||
inline: false,
|
||||
// `annotation: true` appends the sourceMappingURL to the end of
|
||||
// the css file, helping the browser find the sourcemap
|
||||
annotation: true,
|
||||
}
|
||||
: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
name: false,
|
||||
},
|
||||
// Keep the runtime chunk separated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: true,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebook/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebook/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: paths.moduleFileExtensions
|
||||
.map(ext => `.${ext}`)
|
||||
.filter(ext => useTypeScript || !ext.includes('ts')),
|
||||
alias: {
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
'react-native': 'react-native-web',
|
||||
},
|
||||
plugins: [
|
||||
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
|
||||
// guards against forgotten dependencies and such.
|
||||
PnpWebpackPlugin,
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [
|
||||
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
|
||||
// from the current package.
|
||||
PnpWebpackPlugin.moduleLoader(module),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
// Disable require.ensure as it's not a standard language feature.
|
||||
{ parser: { requireEnsure: false } },
|
||||
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
{
|
||||
test: /\.(js|mjs|jsx)$/,
|
||||
enforce: 'pre',
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
||||
eslintPath: require.resolve('eslint'),
|
||||
|
||||
},
|
||||
loader: require.resolve('eslint-loader'),
|
||||
},
|
||||
],
|
||||
include: paths.appSrc,
|
||||
},
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
// match the requirements. When no loader matches it will fall
|
||||
// back to the "file" loader at the end of the loader list.
|
||||
oneOf: [
|
||||
// "url" loader works like "file" loader except that it embeds assets
|
||||
// smaller than specified limit in bytes as data URLs to avoid requests.
|
||||
// A missing `test` is equivalent to a match.
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// Process application JS with Babel.
|
||||
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
|
||||
{
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: paths.appSrc,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
customize: require.resolve(
|
||||
'babel-preset-react-app/webpack-overrides'
|
||||
),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-named-asset-import'),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in ./node_modules/.cache/babel-loader/
|
||||
// directory for faster rebuilds.
|
||||
cacheDirectory: true,
|
||||
cacheCompression: isEnvProduction,
|
||||
compact: isEnvProduction,
|
||||
},
|
||||
},
|
||||
// Process any JS outside of the app with Babel.
|
||||
// Unlike the application JS, we only compile the standard ES features.
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
[
|
||||
require.resolve('babel-preset-react-app/dependencies'),
|
||||
{ helpers: true },
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
cacheCompression: isEnvProduction,
|
||||
|
||||
// If an error happens in a package, it's possible to be
|
||||
// because it was compiled. Thus, we don't want the browser
|
||||
// debugger to show the original code. Instead, the code
|
||||
// being evaluated would be much more helpful.
|
||||
sourceMaps: false,
|
||||
},
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
// In production, we use MiniCSSExtractPlugin to extract that CSS
|
||||
// to a file, but in development "style" loader enables hot editing
|
||||
// of CSS.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
}),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
{
|
||||
test: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
}),
|
||||
},
|
||||
// Opt-in support for SASS (using .scss or .sass extensions).
|
||||
// By default we support SASS Modules with the
|
||||
// extensions .module.scss or .module.sass
|
||||
{
|
||||
test: sassRegex,
|
||||
exclude: sassModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
{
|
||||
test: sassModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
// In production, they would get copied to the `build` folder.
|
||||
// This loader doesn't use a "test" so it will catch all modules
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
loader: require.resolve('file-loader'),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// its runtime that would otherwise be processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
use: { loader: 'worker-loader' }
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin(
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
},
|
||||
isEnvProduction
|
||||
? {
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
)
|
||||
),
|
||||
// Inlines the webpack runtime script. This script is too small to warrant
|
||||
// a network request.
|
||||
isEnvProduction &&
|
||||
shouldInlineRuntimeChunk &&
|
||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||
// It is absolutely essential that NODE_ENV is set to production
|
||||
// during a production build.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
// This is necessary to emit hot updates (currently CSS only):
|
||||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
|
||||
// Watcher doesn't work well if you mistype casing in a path so we use
|
||||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebook/create-react-app/issues/240
|
||||
isEnvDevelopment && new CaseSensitivePathsPlugin(),
|
||||
// If you require a missing module and then `npm install` it, you still have
|
||||
// to restart the development server for Webpack to discover it. This plugin
|
||||
// makes the discovery automatic so you don't have to restart.
|
||||
// See https://github.com/facebook/create-react-app/issues/186
|
||||
isEnvDevelopment &&
|
||||
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
|
||||
isEnvProduction &&
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'static/css/[name].[contenthash:8].css',
|
||||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
||||
}),
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
new ManifestPlugin({
|
||||
fileName: 'asset-manifest.json',
|
||||
publicPath: publicPath,
|
||||
}),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the Webpack build.
|
||||
isEnvProduction &&
|
||||
new WorkboxWebpackPlugin.GenerateSW({
|
||||
clientsClaim: true,
|
||||
exclude: [/\.map$/, /asset-manifest\.json$/],
|
||||
importWorkboxFrom: 'cdn',
|
||||
navigateFallback: publicUrl + '/index.html',
|
||||
navigateFallbackBlacklist: [
|
||||
// Exclude URLs starting with /_, as they're likely an API call
|
||||
new RegExp('^/_'),
|
||||
// Exclude URLs containing a dot, as they're likely a resource in
|
||||
// public/ and not a SPA route
|
||||
new RegExp('/[^/]+\\.[^/]+$'),
|
||||
],
|
||||
}),
|
||||
// TypeScript type checking
|
||||
useTypeScript &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: resolve.sync('typescript', {
|
||||
basedir: paths.appNodeModules,
|
||||
}),
|
||||
async: isEnvDevelopment,
|
||||
useTypescriptIncrementalApi: true,
|
||||
checkSyntacticErrors: true,
|
||||
tsconfig: paths.appTsConfig,
|
||||
reportFiles: [
|
||||
'**',
|
||||
'!**/*.json',
|
||||
'!**/__tests__/**',
|
||||
'!**/?(*.)(spec|test).*',
|
||||
'!**/src/setupProxy.*',
|
||||
'!**/src/setupTests.*',
|
||||
],
|
||||
watch: paths.appSrc,
|
||||
silent: true,
|
||||
// The formatter is invoked directly in WebpackDevServerUtils during development
|
||||
formatter: isEnvProduction ? typescriptFormatter : undefined,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
module: 'empty',
|
||||
dgram: 'empty',
|
||||
dns: 'mock',
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
};
|
104
config/webpackDevServer.config.js
Normal file
104
config/webpackDevServer.config.js
Normal file
@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
|
||||
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
|
||||
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
|
||||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
|
||||
const ignoredFiles = require('react-dev-utils/ignoredFiles');
|
||||
const paths = require('./paths');
|
||||
const fs = require('fs');
|
||||
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
|
||||
module.exports = function(proxy, allowedHost) {
|
||||
return {
|
||||
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
|
||||
// websites from potentially accessing local content through DNS rebinding:
|
||||
// https://github.com/webpack/webpack-dev-server/issues/887
|
||||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
||||
// However, it made several existing use cases such as development in cloud
|
||||
// environment or subdomains in development significantly more complicated:
|
||||
// https://github.com/facebook/create-react-app/issues/2271
|
||||
// https://github.com/facebook/create-react-app/issues/2233
|
||||
// While we're investigating better solutions, for now we will take a
|
||||
// compromise. Since our WDS configuration only serves files in the `public`
|
||||
// folder we won't consider accessing them a vulnerability. However, if you
|
||||
// use the `proxy` feature, it gets more dangerous because it can expose
|
||||
// remote code execution vulnerabilities in backends like Django and Rails.
|
||||
// So we will disable the host check normally, but enable it if you have
|
||||
// specified the `proxy` setting. Finally, we let you override it if you
|
||||
// really know what you're doing with a special environment variable.
|
||||
disableHostCheck:
|
||||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
|
||||
// Enable gzip compression of generated files.
|
||||
compress: true,
|
||||
// Silence WebpackDevServer's own logs since they're generally not useful.
|
||||
// It will still show compile warnings and errors with this setting.
|
||||
clientLogLevel: 'none',
|
||||
// By default WebpackDevServer serves physical files from current directory
|
||||
// in addition to all the virtual build products that it serves from memory.
|
||||
// This is confusing because those files won’t automatically be available in
|
||||
// production build folder unless we copy them. However, copying the whole
|
||||
// project directory is dangerous because we may expose sensitive files.
|
||||
// Instead, we establish a convention that only files in `public` directory
|
||||
// get served. Our build script will copy `public` into the `build` folder.
|
||||
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
|
||||
// Note that we only recommend to use `public` folder as an escape hatch
|
||||
// for files like `favicon.ico`, `manifest.json`, and libraries that are
|
||||
// for some reason broken when imported through Webpack. If you just want to
|
||||
// use an image, put it in `src` and `import` it from JavaScript instead.
|
||||
contentBase: paths.appPublic,
|
||||
// By default files from `contentBase` will not trigger a page reload.
|
||||
watchContentBase: true,
|
||||
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
|
||||
// for the WebpackDevServer client so it can learn when the files were
|
||||
// updated. The WebpackDevServer client is included as an entry point
|
||||
// in the Webpack development configuration. Note that only changes
|
||||
// to CSS are currently hot reloaded. JS changes will refresh the browser.
|
||||
hot: true,
|
||||
// It is important to tell WebpackDevServer to use the same "root" path
|
||||
// as we specified in the config. In development, we always serve from /.
|
||||
publicPath: '/',
|
||||
// WebpackDevServer is noisy by default so we emit custom message instead
|
||||
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebook/create-react-app/issues/293
|
||||
// src/node_modules is not ignored to support absolute imports
|
||||
// https://github.com/facebook/create-react-app/issues/1065
|
||||
watchOptions: {
|
||||
ignored: ignoredFiles(paths.appSrc),
|
||||
},
|
||||
// Enable HTTPS if the HTTPS environment variable is set to 'true'
|
||||
https: protocol === 'https',
|
||||
host,
|
||||
overlay: false,
|
||||
historyApiFallback: {
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebook/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
},
|
||||
public: allowedHost,
|
||||
proxy,
|
||||
before(app, server) {
|
||||
if (fs.existsSync(paths.proxySetup)) {
|
||||
// This registers user provided middleware for proxy reasons
|
||||
require(paths.proxySetup)(app);
|
||||
}
|
||||
|
||||
// This lets us fetch source contents from webpack for the error overlay
|
||||
app.use(evalSourceMapMiddleware(server));
|
||||
// This lets us open files from the runtime error overlay.
|
||||
app.use(errorOverlayMiddleware());
|
||||
|
||||
// This service worker file is effectively a 'no-op' that will reset any
|
||||
// previous service worker registered for the same host:port combination.
|
||||
// We do this in development to avoid hitting the production cache if
|
||||
// it used the same host and port.
|
||||
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
|
||||
app.use(noopServiceWorkerMiddleware());
|
||||
},
|
||||
};
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
enabled: true,
|
||||
host: "localhost",
|
||||
port: 8000
|
||||
};
|
17
embark.json
17
embark.json
@ -1,19 +1,13 @@
|
||||
{
|
||||
"contracts": ["contracts/**"],
|
||||
"app": {
|
||||
"js/dapp.js": ["app/dapp.js"],
|
||||
"js/index.js": ["app/index.js"],
|
||||
"index.html": "app/index.html",
|
||||
"images/": ["app/images/**"]
|
||||
},
|
||||
"buildDir": "dist/",
|
||||
"config": {
|
||||
"contracts": "config/contracts.js",
|
||||
"blockchain": "config/blockchain.js",
|
||||
"storage": "config/storage.js",
|
||||
"contracts": "embarkConfig/contracts.js",
|
||||
"blockchain": "embarkConfig/blockchain.js",
|
||||
"storage": "embarkConfig/storage.js",
|
||||
"namesystem": false,
|
||||
"communication": false,
|
||||
"webserver": "config/webserver.js"
|
||||
"webserver": false
|
||||
},
|
||||
"versions": {
|
||||
"web3": "1.0.0-beta",
|
||||
@ -28,5 +22,6 @@
|
||||
"optimize": true,
|
||||
"optimize-runs": 200
|
||||
}
|
||||
}
|
||||
},
|
||||
"generationDir": "src/embarkArtifacts"
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/development/devpassword"
|
||||
password: "embarkConfig/development/devpassword"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -58,7 +58,7 @@ module.exports = {
|
||||
// When enabled, geth uses POW to mine transactions as it would normally, instead of using POA as it does in --dev mode.
|
||||
// On the first `embark blockchain or embark run` after this option is enabled, geth will create a new chain with a
|
||||
// genesis block, which can be configured using the `genesisBlock` configuration option below.
|
||||
genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
|
||||
genesisBlock: "embarkConfig/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
|
||||
nodiscover: true,
|
||||
maxpeers: 0,
|
||||
proxy: true,
|
||||
@ -66,7 +66,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/privatenet/password"
|
||||
password: "embarkConfig/privatenet/password"
|
||||
}
|
||||
],
|
||||
targetGasLimit: 8000000,
|
||||
@ -82,7 +82,7 @@ module.exports = {
|
||||
networkType: "custom",
|
||||
networkId: 1337,
|
||||
isDev: false,
|
||||
genesisBlock: "config/privatenet/genesis-parity.json", // Genesis block to initiate on first creation of a development node
|
||||
genesisBlock: "embarkConfig/privatenet/genesis-parity.json", // Genesis block to initiate on first creation of a development node
|
||||
datadir: ".embark/privatenet/datadir", // (Geth 1.8.15 and Parity 2.0.4 can use the same base folder, till now they does not conflict with each other)
|
||||
mineWhenNeeded: false,
|
||||
nodiscover: true,
|
||||
@ -92,7 +92,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/privatenet/password"
|
||||
password: "embarkConfig/privatenet/password"
|
||||
}
|
||||
],
|
||||
targetGasLimit: 8000000,
|
||||
@ -108,7 +108,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/testnet/password"
|
||||
password: "embarkConfig/testnet/password"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -119,7 +119,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/testnet/password"
|
||||
password: "embarkConfig/testnet/password"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -135,7 +135,7 @@ module.exports = {
|
||||
{
|
||||
nodeAccounts: true,
|
||||
numAddresses: "1",
|
||||
password: "config/livenet/password"
|
||||
password: "embarkConfig/livenet/password"
|
||||
}
|
||||
]
|
||||
}
|
@ -57,14 +57,11 @@ module.exports = {
|
||||
contracts: {
|
||||
LPVault: {},
|
||||
LiquidPledging: {
|
||||
instanceOf: 'LiquidPledgingMock'
|
||||
instanceOf: 'LiquidPledgingMock'
|
||||
},
|
||||
RecoveryVault: {},
|
||||
LPFactory: {
|
||||
args: {
|
||||
_vaultBase: '$LPVault',
|
||||
_lpBase: '$LiquidPledging',
|
||||
},
|
||||
args: ['$LPVault', '$LiquidPledging'],
|
||||
},
|
||||
// contracts for testing
|
||||
StandardToken: {},
|
||||
@ -80,18 +77,18 @@ module.exports = {
|
||||
// `console.log('we deployed here')`,
|
||||
// `embark.logger.info('we deployed here')`,
|
||||
// `LPFactory.methods.newLP("$accounts[0]", "$RecoveryVault").send({ gas: 7000000 })
|
||||
// .then(({ events }) => {
|
||||
// .then(({ events }) => {
|
||||
// console.log('method ran');
|
||||
// global.LiquidPledging = new web3.eth.Contract(LiquidPledgingMockAbi, events.DeployLiquidPledging.returnValues.liquidPledging);
|
||||
// global.LPVault = new web3.eth.Contract(LPVaultAbi, events.DeployVault.returnValues.vault);
|
||||
// StandardToken.methods.mint(accounts[1], web3.utils.toWei('1000')).send();
|
||||
// StandardToken.methods.approve(global.LiquidPledging.address, '0xFFFFFFFFFFFFFFFF').send({ from: "$accounts[1]" });
|
||||
// })`
|
||||
// .catch(err => console.log('error', err))
|
||||
// `,
|
||||
// .catch(err => console.log('error', err))
|
||||
// `,
|
||||
// `web3.eth.getAccounts().then(accounts => {
|
||||
// return LPFactory.methods.newLP(accounts[0], "$RecoveryVault").send({ gas: 7000000 })
|
||||
// .then(({ events }) => {
|
||||
// .then(({ events }) => {
|
||||
// global.LiquidPledging = new web3.eth.Contract(LiquidPledgingMockAbi, events.DeployLiquidPledging.returnValues.liquidPledging);
|
||||
// global.LPVault = new web3.eth.Contract(LPVaultAbi, events.DeployVault.returnValues.vault);
|
||||
// StandardToken.methods.mint(accounts[1], web3.utils.toWei('1000')).send();
|
1
embarkConfig/development/devpassword
Normal file
1
embarkConfig/development/devpassword
Normal file
@ -0,0 +1 @@
|
||||
|
@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
ipfs_bin: "ipfs",
|
||||
available_providers: ["ipfs"],
|
||||
upload: {
|
||||
@ -28,7 +28,6 @@ module.exports = {
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
enabled: true,
|
||||
upload: {
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
39725
package-lock.json
generated
39725
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
134
package.json
134
package.json
@ -12,9 +12,10 @@
|
||||
"compile:sol": "solcpiler --solc-version v0.4.18+commit.9cf6e910 -i './contracts/**/*.sol' ./node_modules/@aragon/os/contracts/{kernel/Kernel.sol,acl/ACL.sol,apps/AppProxyUpgradeable.sol} --output-sol-dir build/contracts",
|
||||
"compile:js": "babel -d lib/ js/",
|
||||
"compile": "npm run compile:sol && npm run compile:js",
|
||||
"build": "npm run compile",
|
||||
"prepublish": "npm run build",
|
||||
"lint": "eslint app"
|
||||
"lint": "eslint src",
|
||||
"start": "node scripts/start.js",
|
||||
"build": "node scripts/build.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -35,10 +36,11 @@
|
||||
"url": "https://github.com/Giveth/liquidpledging/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.4.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.3",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"eslint": "^5.9.0",
|
||||
"eslint-config-airbnb": "^15.0.1",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-import": "^2.6.0",
|
||||
@ -50,40 +52,156 @@
|
||||
"random-bytes": "^1.0.0",
|
||||
"solcpiler": "1.0.0-beta.8",
|
||||
"web3": "1.0.0-beta.34",
|
||||
"webpack": "4.28.3",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/Giveth/liquidpledging#readme",
|
||||
"dependencies": {
|
||||
"@aragon/os": "3.1.9",
|
||||
"@areknawo/rex": "^2.0.0",
|
||||
"@babel/core": "7.2.2",
|
||||
"@material-ui/core": "^3.6.0",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"@nozbe/watermelondb": "^0.9.0",
|
||||
"@nozbe/with-observables": "^1.0.2",
|
||||
"@svgr/webpack": "4.1.0",
|
||||
"async": "^2.4.0",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "9.0.0",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-loader": "8.0.5",
|
||||
"babel-plugin-named-asset-import": "^0.3.1",
|
||||
"babel-preset-react-app": "^7.0.2",
|
||||
"bfj": "6.1.1",
|
||||
"case-sensitive-paths-webpack-plugin": "2.2.0",
|
||||
"chai": "^4.1.0",
|
||||
"chart.js": "^2.7.3",
|
||||
"cryptocurrency-icons": "^0.9.3",
|
||||
"css-loader": "1.0.0",
|
||||
"cytoscape": "^3.3.0",
|
||||
"cytoscape-cose-bilkent": "^4.0.0",
|
||||
"cytoscape-dagre": "^2.2.2",
|
||||
"dotenv": "6.0.0",
|
||||
"dotenv-expand": "4.2.0",
|
||||
"embark": "^4.1.0-beta.0",
|
||||
"embarkjs-connector-web3": "^4.0.0",
|
||||
"eslint": "^5.9.0",
|
||||
"eslint": "5.12.0",
|
||||
"eslint-config-react-app": "^3.0.8",
|
||||
"eslint-loader": "2.1.1",
|
||||
"eslint-plugin-flowtype": "2.50.1",
|
||||
"eslint-plugin-import": "2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "6.1.2",
|
||||
"eslint-plugin-react": "7.12.4",
|
||||
"eth-contract-class": "^0.0.12",
|
||||
"file-loader": "2.0.0",
|
||||
"formik": "^1.3.2",
|
||||
"fs-extra": "7.0.1",
|
||||
"html-webpack-plugin": "4.0.0-alpha.2",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"ipfs": "^0.34.4",
|
||||
"jest": "23.6.0",
|
||||
"jest-pnp-resolver": "1.0.2",
|
||||
"jest-resolve": "23.6.0",
|
||||
"jest-watch-typeahead": "^0.2.1",
|
||||
"lokijs": "^1.5.6",
|
||||
"material-table": "^1.12.0",
|
||||
"mini-css-extract-plugin": "0.5.0",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.1",
|
||||
"pnp-webpack-plugin": "1.2.1",
|
||||
"postcss-flexbugs-fixes": "4.1.0",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-preset-env": "6.5.0",
|
||||
"postcss-safe-parser": "4.0.1",
|
||||
"pull-file-reader": "^1.0.2",
|
||||
"ramda": "^0.26.1",
|
||||
"react": "^16.8.0",
|
||||
"react": "^16.8.6",
|
||||
"react-app-polyfill": "^0.2.2",
|
||||
"react-chartjs-2": "^2.7.4",
|
||||
"react-cytoscapejs": "^1.1.0",
|
||||
"react-dom": "^16.8.0",
|
||||
"react-dev-utils": "^8.0.0",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-player": "^1.9.3",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-spinners": "^0.5.1",
|
||||
"reselect": "^4.0.0"
|
||||
"reselect": "^4.0.0",
|
||||
"resolve": "1.10.0",
|
||||
"sass-loader": "7.1.0",
|
||||
"style-loader": "0.23.1",
|
||||
"terser-webpack-plugin": "1.2.2",
|
||||
"url-loader": "1.1.2",
|
||||
"webpack": "4.28.3",
|
||||
"webpack-dev-server": "3.1.14",
|
||||
"webpack-manifest-plugin": "2.0.4",
|
||||
"workbox-webpack-plugin": "3.6.3"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"jest": {
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.{js,jsx,ts,tsx}",
|
||||
"!src/**/*.d.ts"
|
||||
],
|
||||
"resolver": "jest-pnp-resolver",
|
||||
"setupFiles": [
|
||||
"react-app-polyfill/jsdom"
|
||||
],
|
||||
"testMatch": [
|
||||
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
|
||||
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,ts,tsx}"
|
||||
],
|
||||
"testEnvironment": "jsdom",
|
||||
"testURL": "http://localhost",
|
||||
"transform": {
|
||||
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
|
||||
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
|
||||
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
|
||||
"^.+\\.module\\.(css|sass|scss)$"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^react-native$": "react-native-web",
|
||||
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
|
||||
},
|
||||
"moduleFileExtensions": [
|
||||
"web.js",
|
||||
"js",
|
||||
"web.ts",
|
||||
"ts",
|
||||
"web.tsx",
|
||||
"tsx",
|
||||
"json",
|
||||
"web.jsx",
|
||||
"jsx",
|
||||
"node"
|
||||
],
|
||||
"watchPlugins": [
|
||||
"C:\\dev\\liquid-funding\\node_modules\\jest-watch-typeahead\\filename.js",
|
||||
"C:\\dev\\liquid-funding\\node_modules\\jest-watch-typeahead\\testname.js"
|
||||
]
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"react-app"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-proposal-class-properties", { "loose": true }],
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
"helpers": true,
|
||||
"regenerator": true
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
}
|
||||
}
|
||||
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
40
public/index.html
Normal file
40
public/index.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Status.im Liquid Funding</title>
|
||||
</head>
|
||||
<body class="container">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="app"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
15
public/manifest.json
Normal file
15
public/manifest.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
192
scripts/build.js
Normal file
192
scripts/build.js
Normal file
@ -0,0 +1,192 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'production';
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const fs = require('fs-extra');
|
||||
const webpack = require('webpack');
|
||||
const bfj = require('bfj');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const paths = require('../config/paths');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
|
||||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
|
||||
const printBuildError = require('react-dev-utils/printBuildError');
|
||||
|
||||
const measureFileSizesBeforeBuild =
|
||||
FileSizeReporter.measureFileSizesBeforeBuild;
|
||||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
|
||||
// These sizes are pretty large. We'll warn for bundles exceeding them.
|
||||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
||||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
||||
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Process CLI arguments
|
||||
const argv = process.argv.slice(2);
|
||||
const writeStatsJson = argv.indexOf('--stats') !== -1;
|
||||
|
||||
// Generate configuration
|
||||
const config = configFactory('production');
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
return measureFileSizesBeforeBuild(paths.appBuild);
|
||||
})
|
||||
.then(previousFileSizes => {
|
||||
// Remove all content but keep the directory so that
|
||||
// if you're in it, you don't end up in Trash
|
||||
fs.emptyDirSync(paths.appBuild);
|
||||
// Merge with the public folder
|
||||
copyPublicFolder();
|
||||
// Start the webpack build
|
||||
return build(previousFileSizes);
|
||||
})
|
||||
.then(
|
||||
({ stats, previousFileSizes, warnings }) => {
|
||||
if (warnings.length) {
|
||||
console.log(chalk.yellow('Compiled with warnings.\n'));
|
||||
console.log(warnings.join('\n\n'));
|
||||
console.log(
|
||||
'\nSearch for the ' +
|
||||
chalk.underline(chalk.yellow('keywords')) +
|
||||
' to learn more about each warning.'
|
||||
);
|
||||
console.log(
|
||||
'To ignore, add ' +
|
||||
chalk.cyan('// eslint-disable-next-line') +
|
||||
' to the line before.\n'
|
||||
);
|
||||
} else {
|
||||
console.log(chalk.green('Compiled successfully.\n'));
|
||||
}
|
||||
|
||||
console.log('File sizes after gzip:\n');
|
||||
printFileSizesAfterBuild(
|
||||
stats,
|
||||
previousFileSizes,
|
||||
paths.appBuild,
|
||||
WARN_AFTER_BUNDLE_GZIP_SIZE,
|
||||
WARN_AFTER_CHUNK_GZIP_SIZE
|
||||
);
|
||||
console.log();
|
||||
|
||||
const appPackage = require(paths.appPackageJson);
|
||||
const publicUrl = paths.publicUrl;
|
||||
const publicPath = config.output.publicPath;
|
||||
const buildFolder = path.relative(process.cwd(), paths.appBuild);
|
||||
printHostingInstructions(
|
||||
appPackage,
|
||||
publicUrl,
|
||||
publicPath,
|
||||
buildFolder,
|
||||
useYarn
|
||||
);
|
||||
},
|
||||
err => {
|
||||
console.log(chalk.red('Failed to compile.\n'));
|
||||
printBuildError(err);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Create the production build and print the deployment instructions.
|
||||
function build(previousFileSizes) {
|
||||
console.log('Creating an optimized production build...');
|
||||
|
||||
let compiler = webpack(config);
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
let messages;
|
||||
if (err) {
|
||||
if (!err.message) {
|
||||
return reject(err);
|
||||
}
|
||||
messages = formatWebpackMessages({
|
||||
errors: [err.message],
|
||||
warnings: [],
|
||||
});
|
||||
} else {
|
||||
messages = formatWebpackMessages(
|
||||
stats.toJson({ all: false, warnings: true, errors: true })
|
||||
);
|
||||
}
|
||||
if (messages.errors.length) {
|
||||
// Only keep the first error. Others are often indicative
|
||||
// of the same problem, but confuse the reader with noise.
|
||||
if (messages.errors.length > 1) {
|
||||
messages.errors.length = 1;
|
||||
}
|
||||
return reject(new Error(messages.errors.join('\n\n')));
|
||||
}
|
||||
if (
|
||||
process.env.CI &&
|
||||
(typeof process.env.CI !== 'string' ||
|
||||
process.env.CI.toLowerCase() !== 'false') &&
|
||||
messages.warnings.length
|
||||
) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'\nTreating warnings as errors because process.env.CI = true.\n' +
|
||||
'Most CI servers set it automatically.\n'
|
||||
)
|
||||
);
|
||||
return reject(new Error(messages.warnings.join('\n\n')));
|
||||
}
|
||||
|
||||
const resolveArgs = {
|
||||
stats,
|
||||
previousFileSizes,
|
||||
warnings: messages.warnings,
|
||||
};
|
||||
if (writeStatsJson) {
|
||||
return bfj
|
||||
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
|
||||
.then(() => resolve(resolveArgs))
|
||||
.catch(error => reject(new Error(error)));
|
||||
}
|
||||
|
||||
return resolve(resolveArgs);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyPublicFolder() {
|
||||
fs.copySync(paths.appPublic, paths.appBuild, {
|
||||
dereference: true,
|
||||
filter: file => file !== paths.appHtml,
|
||||
});
|
||||
}
|
132
scripts/start.js
Normal file
132
scripts/start.js
Normal file
@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const fs = require('fs');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const webpack = require('webpack');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const clearConsole = require('react-dev-utils/clearConsole');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const {
|
||||
choosePort,
|
||||
createCompiler,
|
||||
prepareProxy,
|
||||
prepareUrls,
|
||||
} = require('react-dev-utils/WebpackDevServerUtils');
|
||||
const openBrowser = require('react-dev-utils/openBrowser');
|
||||
const paths = require('../config/paths');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const createDevServerConfig = require('../config/webpackDevServer.config');
|
||||
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Tools like Cloud9 rely on this.
|
||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
||||
const HOST = process.env.HOST || '0.0.0.0';
|
||||
|
||||
if (process.env.HOST) {
|
||||
console.log(
|
||||
chalk.cyan(
|
||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
||||
chalk.bold(process.env.HOST)
|
||||
)}`
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
|
||||
);
|
||||
console.log(
|
||||
`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}`
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
// We require that you explictly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||
return choosePort(HOST, DEFAULT_PORT);
|
||||
})
|
||||
.then(port => {
|
||||
if (port == null) {
|
||||
// We have not found a port.
|
||||
return;
|
||||
}
|
||||
const config = configFactory('development');
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const appName = require(paths.appPackageJson).name;
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
const urls = prepareUrls(protocol, HOST, port);
|
||||
const devSocket = {
|
||||
warnings: warnings =>
|
||||
devServer.sockWrite(devServer.sockets, 'warnings', warnings),
|
||||
errors: errors =>
|
||||
devServer.sockWrite(devServer.sockets, 'errors', errors),
|
||||
};
|
||||
// Create a webpack compiler that is configured with custom messages.
|
||||
const compiler = createCompiler({
|
||||
appName,
|
||||
config,
|
||||
devSocket,
|
||||
urls,
|
||||
useYarn,
|
||||
useTypeScript,
|
||||
webpack,
|
||||
});
|
||||
// Load proxy config
|
||||
const proxySetting = require(paths.appPackageJson).proxy;
|
||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
||||
// Serve webpack assets generated by the compiler over a web server.
|
||||
const serverConfig = createDevServerConfig(
|
||||
proxyConfig,
|
||||
urls.lanUrlForConfig
|
||||
);
|
||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
||||
// Launch WebpackDevServer.
|
||||
devServer.listen(port, HOST, err => {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
console.log(chalk.cyan('Starting the development server...\n'));
|
||||
openBrowser(urls.localUrlForBrowser);
|
||||
});
|
||||
|
||||
['SIGINT', 'SIGTERM'].forEach(function(sig) {
|
||||
process.on(sig, function() {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
60
scripts/test.js
Normal file
60
scripts/test.js
Normal file
@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'test';
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.PUBLIC_URL = '';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const jest = require('jest');
|
||||
const execSync = require('child_process').execSync;
|
||||
let argv = process.argv.slice(2);
|
||||
|
||||
function isInGitRepository() {
|
||||
try {
|
||||
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isInMercurialRepository() {
|
||||
try {
|
||||
execSync('hg --cwd . root', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Watch unless on CI, in coverage mode, explicitly adding `--no-watch`,
|
||||
// or explicitly running all tests
|
||||
if (
|
||||
!process.env.CI &&
|
||||
argv.indexOf('--coverage') === -1 &&
|
||||
argv.indexOf('--no-watch') === -1 &&
|
||||
argv.indexOf('--watchAll') === -1
|
||||
) {
|
||||
// https://github.com/facebook/create-react-app/issues/5210
|
||||
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
|
||||
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
||||
}
|
||||
|
||||
// Jest doesn't have this option so we'll remove it
|
||||
if (argv.indexOf('--no-watch') !== -1) {
|
||||
argv = argv.filter(arg => arg !== '--no-watch');
|
||||
}
|
||||
|
||||
|
||||
jest.run(argv);
|
@ -1,7 +1,7 @@
|
||||
import database from '../db'
|
||||
import { Q } from '@nozbe/watermelondb'
|
||||
import { getPledgesWithDelegates } from './pledges'
|
||||
import { getProfilesById, getProfileById } from './profiles'
|
||||
import { getProfilesById } from './profiles'
|
||||
|
||||
const delegatesCollection = database.collections.get('delegates')
|
||||
export const getDelegateProfiles = async pledges => {
|
||||
@ -24,9 +24,9 @@ const delegateRecordExists = (profile, pledge, idx, existing) => {
|
||||
const record = existing.find(delegate => {
|
||||
const { delegateIndex } = delegate
|
||||
if (
|
||||
profile.id == delegate.profile.id &&
|
||||
pledge.idPledge == delegate.idPledge &&
|
||||
idx == delegateIndex
|
||||
profile.id === delegate.profile.id &&
|
||||
pledge.idPledge === delegate.idPledge &&
|
||||
idx === delegateIndex
|
||||
) return true
|
||||
return false
|
||||
})
|
||||
@ -38,7 +38,7 @@ const batchAddDelegates = async (pledges, profiles, existing) => {
|
||||
pledges.forEach(pledge => {
|
||||
const { delegates } = pledge
|
||||
delegates.forEach((delegateInfo, idx) => {
|
||||
const profile = profiles.find(p => p.idProfile == delegateInfo.idDelegate)
|
||||
const profile = profiles.find(p => p.idProfile === delegateInfo.idDelegate)
|
||||
const exists = delegateRecordExists(profile, pledge, idx+1, existing)
|
||||
if (!exists) {
|
||||
batch.push(
|
@ -54,9 +54,7 @@ export const getLpEventById = async id => {
|
||||
|
||||
export const getLastBlockStored = async () => {
|
||||
const col = await lpCollection.query().fetch()
|
||||
const blockNumber = col.length
|
||||
? col.sort((a,b) => b.blockNumber - a.blockNumber)[0].blockNumber
|
||||
: 0
|
||||
const blockNumber = col.length ? col.sort((a,b) => b.blockNumber - a.blockNumber)[0].blockNumber : 0
|
||||
return blockNumber
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { getProfilesById } from './profiles'
|
||||
|
||||
const createPledge = (pledge, data, profiles) => {
|
||||
const { id, owner, amount, blockNumber, token, commitTime, nDelegates, pledgeState, intendedProject, delegates } = data
|
||||
const profile = profiles.find(p => p.idProfile == owner)
|
||||
const profile = profiles.find(p => p.idProfile === owner)
|
||||
pledge.idPledge = Number(id)
|
||||
pledge.owner = Number(owner)
|
||||
pledge.amount = amount
|
||||
@ -37,9 +37,7 @@ export const batchAddPledges = async (pledges, profiles = []) => {
|
||||
}
|
||||
|
||||
const getLastPledge = pledges => {
|
||||
const idPledge = pledges.length
|
||||
? pledges.sort((a,b) => b.idPledge - a.idPledge)[0].idPledge
|
||||
: 0
|
||||
const idPledge = pledges.length ? pledges.sort((a,b) => b.idPledge - a.idPledge)[0].idPledge : 0
|
||||
return idPledge
|
||||
}
|
||||
export const getAndAddPledges = async () => {
|
@ -41,9 +41,7 @@ export const getVaultEventById = async id => {
|
||||
|
||||
export const getLastBlockStored = async () => {
|
||||
const col = await vaultCollection.query().fetch()
|
||||
const blockNumber = col.length
|
||||
? col.sort((a,b) => b.blockNumber - a.blockNumber)[0].blockNumber
|
||||
: 0
|
||||
const blockNumber = col.length ? col.sort((a,b) => b.blockNumber - a.blockNumber)[0].blockNumber : 0
|
||||
return blockNumber
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*global web3*/
|
||||
import React, { createRef } from 'react'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import {TextField, Button, MenuItem, Snackbar, InputAdornment} from '@material-ui/core'
|
||||
import CloudUpload from '@material-ui/icons/CloudUpload'
|
||||
import { MySnackbarContentWrapper } from './base/SnackBars'
|
||||
@ -56,13 +56,11 @@ let uploadInput = createRef()
|
||||
const AddFunder = ({ appendFundProfile }) => (
|
||||
<Formik
|
||||
initialValues={{ adminType: FUNDER, funderName: '', funderDescription: '', commitTime : '' }}
|
||||
onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => {
|
||||
onSubmit={async (values, { setSubmitting: _setSubmitting, resetForm: _resetForm, setStatus }) => {
|
||||
const { adminType, funderName, funderDescription, commitTime } = values
|
||||
const account = await web3.eth.getCoinbase()
|
||||
//TODO add field for parent project
|
||||
const args = adminType === PROJECT
|
||||
? [funderName, funderDescription, account, 0, hoursToSeconds(commitTime), 0]
|
||||
: [funderName, funderDescription, hoursToSeconds(commitTime), 0]
|
||||
const args = adminType === PROJECT ? [funderName, funderDescription, account, 0, hoursToSeconds(commitTime), 0] : [funderName, funderDescription, hoursToSeconds(commitTime), 0]
|
||||
const isFunder = adminType === FUNDER
|
||||
const sendFn = sendFns[adminType]
|
||||
sendFn(...args)
|
||||
@ -91,8 +89,8 @@ const AddFunder = ({ appendFundProfile }) => (
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
@ -131,17 +129,19 @@ const AddFunder = ({ appendFundProfile }) => (
|
||||
value={values.funderName || ''}
|
||||
/>
|
||||
<input
|
||||
ref={(input) => { uploadInput = input }}
|
||||
ref={(input) => {
|
||||
uploadInput = input
|
||||
}}
|
||||
type="file"
|
||||
multiple
|
||||
onChange={
|
||||
(e) => captureFile(
|
||||
e,
|
||||
hash => setFieldValue('funderDescription', hash),
|
||||
profileImg => setStatus({ profileImg })
|
||||
)
|
||||
(e) => captureFile(
|
||||
e,
|
||||
hash => setFieldValue('funderDescription', hash),
|
||||
profileImg => setStatus({profileImg})
|
||||
)
|
||||
}
|
||||
style={{ display: 'none' }} />
|
||||
style={{display: 'none'}}/>
|
||||
<TextField
|
||||
id="funderDescription"
|
||||
name="funderDescription"
|
||||
@ -178,14 +178,14 @@ const AddFunder = ({ appendFundProfile }) => (
|
||||
{`ADD ${buttonLabel[values.adminType]} PROFILE`}
|
||||
</Button>
|
||||
{status && status.snackbar && <Snackbar
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
open={!!status.snackbar}
|
||||
autoHideDuration={6000}
|
||||
onClose={() => setStatus(null)}
|
||||
>
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
open={!!status.snackbar}
|
||||
autoHideDuration={6000}
|
||||
onClose={() => setStatus(null)}
|
||||
>
|
||||
<MySnackbarContentWrapper
|
||||
onClose={() => setStatus(null)}
|
||||
variant={status.snackbar.variant}
|
@ -1,7 +1,7 @@
|
||||
/*global web3*/
|
||||
import React, { useContext, useState, useEffect } from 'react';
|
||||
import { Formik } from 'formik';
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging';
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
@ -15,8 +15,8 @@ import { getLpAllowance, standardTokenApproval } from '../utils/initialize'
|
||||
import { FundingContext } from '../context'
|
||||
|
||||
const { donate } = LiquidPledging.methods
|
||||
const hoursToSeconds = hours => hours * 60 * 60
|
||||
const addFunderSucessMsg = response => {
|
||||
const _hoursToSeconds = hours => hours * 60 * 60
|
||||
const _addFunderSucessMsg = response => {
|
||||
const { events: { GiverAdded: { returnValues: { idGiver } } } } = response
|
||||
return `Funder created with ID of ${idGiver}`
|
||||
}
|
||||
@ -64,7 +64,7 @@ const CreateFunding = ({ refreshTable }) => {
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{ funderId: '', receiverId: '', tokenAddress : '', amount: '' }}
|
||||
onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => {
|
||||
onSubmit={async (values, { setSubmitting: _setSubmitting, resetForm: _resetForm, setStatus }) => {
|
||||
const { funderId, receiverId, tokenAddress, amount } = values
|
||||
const args = [funderId, receiverId, tokenAddress, web3.utils.toWei(amount, 'ether')];
|
||||
|
||||
@ -72,30 +72,30 @@ const CreateFunding = ({ refreshTable }) => {
|
||||
|
||||
const estimateGas = await toSend.estimateGas()
|
||||
|
||||
toSend.send({ from: account, gas: estimateGas + 2000 })
|
||||
.then(res => {
|
||||
console.log({res})
|
||||
setStatus({
|
||||
snackbar: { variant: 'success', message: 'funding provided!' }
|
||||
})
|
||||
refreshTable()
|
||||
})
|
||||
.catch(e => {
|
||||
console.log({e})
|
||||
setStatus({
|
||||
snackbar: { variant: 'error', message: 'There was an error' }
|
||||
})
|
||||
})
|
||||
toSend.send({from: account, gas: estimateGas + 2000})
|
||||
.then(res => {
|
||||
console.log({res})
|
||||
setStatus({
|
||||
snackbar: {variant: 'success', message: 'funding provided!'}
|
||||
})
|
||||
refreshTable()
|
||||
})
|
||||
.catch(e => {
|
||||
console.log({e})
|
||||
setStatus({
|
||||
snackbar: {variant: 'error', message: 'There was an error'}
|
||||
})
|
||||
})
|
||||
}}
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue,
|
||||
setFieldValue: _setFieldValue,
|
||||
setStatus,
|
||||
status
|
||||
}) => (
|
||||
@ -136,11 +136,11 @@ const CreateFunding = ({ refreshTable }) => {
|
||||
value={values.tokenAddress || ''}
|
||||
>
|
||||
{currencies.map((option, idx) => (
|
||||
<MenuItem style={{ display: 'flex', alignItems: 'center' }} key={option.value} value={option.value}>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }} >
|
||||
<MenuItem style={{display: 'flex', alignItems: 'center'}} key={option.value} value={option.value}>
|
||||
<div style={{display: 'flex', alignItems: 'center'}}>
|
||||
{option.icon || <img
|
||||
src={option.img || `${TOKEN_ICON_API}/${option.value}.png`}
|
||||
style={{ width: option.width, marginRight: '3%' }}
|
||||
src={option.img || `${TOKEN_ICON_API}/${option.value}.png`}
|
||||
style={{width: option.width, marginRight: '3%'}}
|
||||
/>}
|
||||
{option.label}
|
||||
<span style={{ marginLeft: '10%' }}>Your Balance: <strong>{balances[option.value]}</strong></span>
|
||||
@ -176,14 +176,14 @@ const CreateFunding = ({ refreshTable }) => {
|
||||
PROVIDE FUNDING
|
||||
</Button>
|
||||
{status && <Snackbar
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
open={!!status.snackbar}
|
||||
autoHideDuration={6000}
|
||||
onClose={() => setStatus(null)}
|
||||
>
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
open={!!status.snackbar}
|
||||
autoHideDuration={6000}
|
||||
onClose={() => setStatus(null)}
|
||||
>
|
||||
<MySnackbarContentWrapper
|
||||
onClose={() => setStatus(null)}
|
||||
variant={status.snackbar.variant}
|
||||
@ -193,6 +193,7 @@ const CreateFunding = ({ refreshTable }) => {
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
)}
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateFunding
|
@ -1,6 +1,6 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import MaterialTable from 'material-table'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import withObservables from '@nozbe/with-observables'
|
||||
import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider'
|
||||
import ProfileUrlViewer from './image/ProfileUrlViewer'
|
||||
@ -9,7 +9,9 @@ import { FundingContext } from '../context'
|
||||
const { cancelProject } = LiquidPledging.methods
|
||||
|
||||
const convertToHours = seconds => seconds / 60 / 60
|
||||
const cancelText = canceled => canceled ? 'Yes' : 'No'
|
||||
const cancelText = canceled => {
|
||||
return canceled ? 'Yes' : 'No'
|
||||
}
|
||||
const formatField = field => ({
|
||||
...field.getFields(),
|
||||
commitTime: convertToHours(field.commitTime),
|
||||
@ -35,14 +37,14 @@ const FunderProfilesTable = ({ profiles }) => (
|
||||
actions={[
|
||||
rowData => ({
|
||||
icon: 'cancel',
|
||||
disabled: !account || rowData.addr.toLowerCase() != account.toLowerCase(),
|
||||
disabled: !account || rowData.addr.toLowerCase() !== account.toLowerCase(),
|
||||
tooltip: 'Cancel',
|
||||
onClick: (event, rowData) => {
|
||||
cancelProject(rowData.idProject || rowData.idProfile)
|
||||
.send()
|
||||
.then(async res => {
|
||||
console.log({res})
|
||||
const profile = profiles.find(p => p.idProfile == rowData.idProfile)
|
||||
const profile = profiles.find(p => p.idProfile === rowData.idProfile)
|
||||
await profile.markAsCanceled()
|
||||
})
|
||||
}
|
221
src/components/MainCointainer.jsx
Normal file
221
src/components/MainCointainer.jsx
Normal file
@ -0,0 +1,221 @@
|
||||
import React from 'react';
|
||||
import { Route, Link, Switch } from 'react-router-dom'
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Drawer from '@material-ui/core/Drawer';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import List from '@material-ui/core/List';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import MenuIcon from '@material-ui/icons/Menu';
|
||||
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
|
||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import InboxIcon from '@material-ui/icons/MoveToInbox';
|
||||
import { ScaleLoader } from 'react-spinners'
|
||||
import FundsManagement from './FundsManagement'
|
||||
import ContractAdmin from './ContractAdmin'
|
||||
import TransferGraph from './TransfersGraph'
|
||||
import Dashboard from './Dashboard'
|
||||
import Project from './projects/Project'
|
||||
import BackProject from './projects/BackProject'
|
||||
import CreateProject from './projects/CreateProject'
|
||||
|
||||
const drawerWidth = 240
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
},
|
||||
appBar: {
|
||||
transition: theme.transitions.create(['margin', 'width'], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
},
|
||||
appBarShift: {
|
||||
width: `calc(100% - ${drawerWidth}px)`,
|
||||
marginLeft: drawerWidth,
|
||||
transition: theme.transitions.create(['margin', 'width'], {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
},
|
||||
appBarBg: {
|
||||
backgroundColor: '#111735'
|
||||
},
|
||||
menuButton: {
|
||||
marginLeft: 12,
|
||||
marginRight: 20,
|
||||
},
|
||||
hide: {
|
||||
display: 'none',
|
||||
},
|
||||
drawer: {
|
||||
width: drawerWidth,
|
||||
flexShrink: 0,
|
||||
},
|
||||
drawerPaper: {
|
||||
width: drawerWidth,
|
||||
},
|
||||
drawerHeader: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0 8px',
|
||||
...theme.mixins.toolbar,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
padding: theme.spacing.unit * 3,
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
marginLeft: -drawerWidth,
|
||||
},
|
||||
contentShift: {
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
marginLeft: 0,
|
||||
},
|
||||
link: {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
})
|
||||
|
||||
class PersistentDrawerLeft extends React.Component {
|
||||
state = {
|
||||
open: false,
|
||||
};
|
||||
|
||||
handleDrawerOpen = () => {
|
||||
this.setState({ open: true })
|
||||
};
|
||||
|
||||
handleDrawerClose = () => {
|
||||
this.setState({ open: false })
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes, theme, loading } = this.props
|
||||
const { open } = this.state
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<CssBaseline />
|
||||
<AppBar
|
||||
position="fixed"
|
||||
className={classNames(classes.appBar, classes.appBarBg, {
|
||||
[classes.appBarShift]: open,
|
||||
})}
|
||||
>
|
||||
<Toolbar disableGutters={!open}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="Open drawer"
|
||||
onClick={this.handleDrawerOpen}
|
||||
className={classNames(classes.menuButton, open && !loading && classes.hide)}
|
||||
>
|
||||
{loading && <ScaleLoader
|
||||
sizeUnit={'px'}
|
||||
height={20}
|
||||
width={2}
|
||||
margin="3px"
|
||||
color={'#FFFFFF'}
|
||||
/>}
|
||||
{!loading && <MenuIcon/>}
|
||||
</IconButton>
|
||||
<Typography variant="h6" color="inherit" noWrap>
|
||||
Liquid Funding
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Drawer
|
||||
className={classes.drawer}
|
||||
variant="persistent"
|
||||
anchor="left"
|
||||
open={open}
|
||||
classes={{
|
||||
paper: classes.drawerPaper,
|
||||
}}
|
||||
>
|
||||
<div className={classes.drawerHeader}>
|
||||
<IconButton onClick={this.handleDrawerClose}>
|
||||
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
||||
</IconButton>
|
||||
</div>
|
||||
<Divider />
|
||||
<List>
|
||||
<Link to="/dashboard" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Dashboard" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/funds-management/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Funds Management" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/insights/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Insights" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<List>
|
||||
<Link to="/admin/" className={classes.link}>
|
||||
<ListItem button>
|
||||
<ListItemIcon><InboxIcon /></ListItemIcon>
|
||||
<ListItemText primary="Admin" />
|
||||
</ListItem>
|
||||
</Link>
|
||||
</List>
|
||||
<Divider />
|
||||
</Drawer>
|
||||
<main
|
||||
className={classNames(classes.content, {
|
||||
[classes.contentShift]: open,
|
||||
})}
|
||||
>
|
||||
<div className={classes.drawerHeader} />
|
||||
<div className={classNames(classes.appBar)}>
|
||||
<Switch>
|
||||
<Route path="/(|dashboard)" component={Dashboard} />
|
||||
<Route path="/admin" component={ContractAdmin} />
|
||||
<Route path="/funds-management" render={() => <FundsManagement open={open} />} />
|
||||
<Route path="/insights" component={TransferGraph} />
|
||||
<Route path="/project/:id" component={Project} />
|
||||
<Route path="/create-project/" render={(props) => <CreateProject {...props} />} />
|
||||
<Route path="/back-project/:id" component={BackProject} />
|
||||
</Switch>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PersistentDrawerLeft.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
loading: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default withStyles(styles, { withTheme: true })(PersistentDrawerLeft)
|
@ -7,8 +7,10 @@ import { getTokenLabel } from '../utils/currencies'
|
||||
import TransferCard from './table/TransferCard'
|
||||
import WithdrawCard from './table/WithdrawCard'
|
||||
|
||||
const convertToHours = seconds => seconds / 60 / 60
|
||||
const projectText = project => project === '0' ? 'N/A' : project
|
||||
const _convertToHours = seconds => seconds / 60 / 60
|
||||
const projectText = project => {
|
||||
return project === '0' ? 'N/A' : project
|
||||
}
|
||||
const pledgeStateMap = {
|
||||
0: 'Pledged',
|
||||
1: 'Paying',
|
||||
@ -49,7 +51,7 @@ class PledgesTable extends Component {
|
||||
pledges.some((pledge, idx) => {
|
||||
const current = data[idx]
|
||||
if (current) {
|
||||
if (toEther(pledge.amount) != current.amount || pledgeStateMap[pledge.pledgeState] != current.pledgeState) this.setData()
|
||||
if (toEther(pledge.amount) !== current.amount || pledgeStateMap[pledge.pledgeState] !== current.pledgeState) this.setData()
|
||||
}
|
||||
})
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
|
||||
const { setMockedTime } = LiquidPledging.methods
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
@ -8,7 +8,6 @@ import CloseIcon from '@material-ui/icons/Close';
|
||||
import green from '@material-ui/core/colors/green';
|
||||
import amber from '@material-ui/core/colors/amber';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import SnackbarContent from '@material-ui/core/SnackbarContent';
|
||||
import WarningIcon from '@material-ui/icons/Warning';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
131
src/components/dashboard/FundingSummary.jsx
Normal file
131
src/components/dashboard/FundingSummary.jsx
Normal file
@ -0,0 +1,131 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import withObservables from '@nozbe/with-observables'
|
||||
import { Q } from '@nozbe/watermelondb'
|
||||
import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import LinearProgress from '@material-ui/core/LinearProgress'
|
||||
import { getDepositWithdrawTotals, getPledgesWaitingCommit } from '../../selectors/pledging'
|
||||
import { getTokenAddress } from '../../utils/currencies'
|
||||
|
||||
const styles = {
|
||||
card: {
|
||||
minWidth: 275,
|
||||
},
|
||||
cardTitle: {
|
||||
paddingBottom: '1rem'
|
||||
},
|
||||
fundingSummaries: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center'
|
||||
},
|
||||
bullet: {
|
||||
display: 'inline-block',
|
||||
margin: '0 2px',
|
||||
transform: 'scale(0.8)',
|
||||
},
|
||||
title: {
|
||||
fontSize: 14,
|
||||
},
|
||||
pos: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
linearColorPrimary: {
|
||||
backgroundColor: '#b2dfdb',
|
||||
},
|
||||
linearBarColorPrimary: {
|
||||
backgroundColor: '#00695c',
|
||||
},
|
||||
titleText: {
|
||||
textAlign: 'center',
|
||||
paddingTop: '2rem'
|
||||
}
|
||||
}
|
||||
|
||||
const getNet = (deposits, withdraws) => Number(deposits) - Number(withdraws)
|
||||
const getValue = (deposits, withdraws) => (getNet(deposits, withdraws) / Number(deposits)) * 100
|
||||
function SimpleCard(props) {
|
||||
const { classes, title, transfers, pledges, vaultEvents } = props
|
||||
|
||||
return (
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography variant="h5" className={classes.cardTitle}>
|
||||
{title}
|
||||
</Typography>
|
||||
{!!transfers && !!pledges.length &&
|
||||
Object.entries(getDepositWithdrawTotals({transfers, pledges, vaultEvents}))
|
||||
.map(token => {
|
||||
const [name, amounts] = token
|
||||
const {deposits, withdraws} = amounts
|
||||
const address = getTokenAddress(name)
|
||||
const pledgesForCommit = getPledgesWaitingCommit({pledges}).filter(p => p.token === address)
|
||||
return (
|
||||
<Card key={name}>
|
||||
<Typography variant="h5" className={classes.titleText}>
|
||||
{name}
|
||||
</Typography>
|
||||
<CardContent className={classes.fundingSummaries}>
|
||||
<Typography variant="h3">
|
||||
{Number(deposits) - Number(withdraws || 0)}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'total'} className={classes.pos} color="textSecondary">
|
||||
Remaining In Pledges
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
{deposits}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'withdraw'} className={classes.pos} color="textSecondary">
|
||||
Funded
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
{withdraws || 0}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'deposit'} className={classes.pos} color="textSecondary">
|
||||
Withdrawn
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
{pledgesForCommit.length}
|
||||
</Typography>
|
||||
<Typography variant="h6" key={name + 'veto/approve'} className={classes.pos} color="textSecondary">
|
||||
Pledges that can be vetoed / approved
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<LinearProgress
|
||||
classes={{
|
||||
colorPrimary: classes.linearColorPrimary,
|
||||
barColorPrimary: classes.linearBarColorPrimary,
|
||||
}}
|
||||
color="primary"
|
||||
variant="buffer"
|
||||
value={getValue(deposits, withdraws)}
|
||||
valueBuffer={100}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
SimpleCard.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
title: PropTypes.string,
|
||||
pledges: PropTypes.array.isRequired,
|
||||
transfers: PropTypes.array.isRequired,
|
||||
vaultEvents: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
const styledCard = withStyles(styles)(SimpleCard)
|
||||
export default withDatabase(withObservables([], ({ database }) => ({
|
||||
transfers: database.collections.get('lp_events').query(
|
||||
Q.where('event', 'Transfer')
|
||||
).observe(),
|
||||
vaultEvents : database.collections.get('vault_events').query().observe()
|
||||
}))(styledCard))
|
||||
|
23
src/components/image/ImageViewer.jsx
Normal file
23
src/components/image/ImageViewer.jsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react'
|
||||
|
||||
const docType = doc => {
|
||||
const suffix = doc.name.split('.')
|
||||
return suffix.slice(-1)[0]
|
||||
}
|
||||
|
||||
const ImageViewer = ({status}) => {
|
||||
return (
|
||||
<div>
|
||||
{status && status.profileImg &&
|
||||
<div>
|
||||
{['jpg', 'gif', 'png'].includes(docType(status.profileImg)) &&
|
||||
<img src={status.profileImg.img} alt="ipfs" style={{maxWidth: '90%'}}/>}
|
||||
{docType(status.profileImg) === 'pdf' &&
|
||||
<iframe src={status.profileImg.img} style={{width: '100%', height: '90%'}}/>}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ImageViewer;
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../../embarkArtifacts/contracts/LiquidPledging'
|
||||
import withObservables from '@nozbe/with-observables'
|
||||
import { Q } from '@nozbe/watermelondb'
|
||||
import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider'
|
||||
@ -89,14 +89,14 @@ const SubmissionSection = ({ classes, profiles, delegatePledges, projectId, open
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue,
|
||||
setStatus,
|
||||
status
|
||||
setFieldValue: _setFieldValue,
|
||||
setStatus: _setStatus,
|
||||
status: _status
|
||||
}) => {
|
||||
const filteredPledges = values.delegateProfile ? delegatePledges.filter(
|
||||
d => d.profile.id === values.delegateProfile.id && d.pledgeData.amount !== '0' && d.pledgeData.pledgeState === 0 && d.pledgeData.intendedProject === 0
|
||||
@ -124,52 +124,56 @@ const SubmissionSection = ({ classes, profiles, delegatePledges, projectId, open
|
||||
value={values.delegateProfile || ''}
|
||||
>
|
||||
{profiles && profiles.map(profile => (
|
||||
<MenuItem style={{ display: 'flex', alignItems: 'center' }} key={profile.name} value={profile}>
|
||||
<MenuItem style={{display: 'flex', alignItems: 'center'}} key={profile.name} value={profile}>
|
||||
{profile.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
{filteredPledges && <TextField
|
||||
className={classes.textField}
|
||||
id="delegatePledge"
|
||||
name="delegatePledge"
|
||||
select
|
||||
label="Select Pledge for Funding"
|
||||
placeholder="Select Pledge for Funding"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.delegatePledge || ''}
|
||||
>
|
||||
className={classes.textField}
|
||||
id="delegatePledge"
|
||||
name="delegatePledge"
|
||||
select
|
||||
label="Select Pledge for Funding"
|
||||
placeholder="Select Pledge for Funding"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.delegatePledge || ''}
|
||||
>
|
||||
{filteredPledges.map(pledge => (
|
||||
<MenuItem style={{ display: 'flex', alignItems: 'center' }} key={pledge.idPledge} value={pledge.idPledge}>
|
||||
<MenuItem style={{display: 'flex', alignItems: 'center'}} key={pledge.idPledge} value={pledge.idPledge}>
|
||||
{`Pledge no: ${pledge.idPledge} - Amount: ${toEther(pledge.pledgeData.amount)} ${getTokenLabel(pledge.pledgeData.token)}`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>}
|
||||
{values.delegatePledge && <TextField
|
||||
autoFocus
|
||||
margin="normal"
|
||||
id="amount"
|
||||
name="amount"
|
||||
label="Amount to transfer"
|
||||
placeholder="Amount to transfer"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
fullWidth
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.amount || ''}
|
||||
autoFocus
|
||||
margin="normal"
|
||||
id="amount"
|
||||
name="amount"
|
||||
label="Amount to transfer"
|
||||
placeholder="Amount to transfer"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
fullWidth
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.amount || ''}
|
||||
/>}
|
||||
{values.amount && <Button type="submit" color="primary" variant="contained" style={{ height: '50px', width: '100%' }}>Submit for Funding</Button>}
|
||||
{values.amount &&
|
||||
<Button type="submit" color="primary" variant="contained" style={{height: '50px', width: '100%'}}>Submit for
|
||||
Funding</Button>}
|
||||
</form>
|
||||
) }
|
||||
)
|
||||
}
|
||||
}
|
||||
</Formik>
|
||||
)}
|
||||
)
|
||||
}
|
||||
|
||||
function BackProject({classes, match, profile, delegates, projectAddedEvents, delegateAddedEvents}) {
|
||||
function BackProject({classes, match, profile, delegates: _delegates, projectAddedEvents, delegateAddedEvents: _delegateAddedEvents}) {
|
||||
const projectId = match.params.id
|
||||
const { manifest, delegateProfiles, openSnackBar } = useProjectData(projectId, profile, projectAddedEvents)
|
||||
const delegatePledges = useProfileData(delegateProfiles)
|
@ -1,6 +1,7 @@
|
||||
/*global Buffer*/
|
||||
import React, { createRef, useState, useContext } from 'react'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../../embarkArtifacts/contracts/LiquidPledging'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
@ -136,7 +137,7 @@ const SubmissionSection = ({ classes, history }) => {
|
||||
const manifest = createJSON(values)
|
||||
let fileLists = []
|
||||
Object.keys(uploads).forEach(k => {
|
||||
fileLists = [ ...fileLists, formatForIpfs(uploads[k][0]) ]
|
||||
fileLists = [...fileLists, formatForIpfs(uploads[k][0])]
|
||||
})
|
||||
fileLists.push({
|
||||
path: '/root/manifest.json', content: Buffer.from(manifest)
|
||||
@ -164,8 +165,8 @@ const SubmissionSection = ({ classes, history }) => {
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
@ -177,22 +178,24 @@ const SubmissionSection = ({ classes, history }) => {
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={classes.submissionRoot}>
|
||||
<input
|
||||
ref={(input) => { uploadInput = input }}
|
||||
ref={(input) => {
|
||||
uploadInput = input
|
||||
}}
|
||||
type="file"
|
||||
multiple
|
||||
onChange={
|
||||
(e) => {
|
||||
const file = e.target.files
|
||||
const { activeField } = status
|
||||
setFieldValue(activeField, file[0]['name'])
|
||||
setUploads({ ...uploads, [activeField]: file })
|
||||
setStatus({
|
||||
...status,
|
||||
activeField: null
|
||||
})
|
||||
(e) => {
|
||||
const file = e.target.files
|
||||
const {activeField} = status
|
||||
setFieldValue(activeField, file[0]['name'])
|
||||
setUploads({...uploads, [activeField]: file})
|
||||
setStatus({
|
||||
...status,
|
||||
activeField: null
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
style={{ display: 'none' }}
|
||||
style={{display: 'none'}}
|
||||
/>
|
||||
<TextField
|
||||
className={classes.textField}
|
||||
@ -362,9 +365,9 @@ const SubmissionSection = ({ classes, history }) => {
|
||||
control={
|
||||
<Switch
|
||||
id="isPlaying"
|
||||
checked={values.isPlaying}
|
||||
onChange={handleChange}
|
||||
value={values.isPlaying}
|
||||
checked={values.isPlaying}
|
||||
onChange={handleChange}
|
||||
value={values.isPlaying}
|
||||
/>
|
||||
}
|
||||
label="Autoplay video?"
|
@ -1,5 +1,5 @@
|
||||
/*global web3*/
|
||||
import React, { useMemo } from 'react'
|
||||
import React, { useMemo, Fragment } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button'
|
||||
@ -93,7 +93,7 @@ const styles = theme => ({
|
||||
}
|
||||
})
|
||||
|
||||
function getReceivedAmount(id, transfers){
|
||||
function _getReceivedAmount(id, transfers){
|
||||
return transfers
|
||||
.filter(t => t.returnValues.to === id)
|
||||
.reduce((pv, cv) => {
|
||||
@ -102,7 +102,7 @@ function getReceivedAmount(id, transfers){
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function getWithdrawnAmount(id, transfers){
|
||||
function _getWithdrawnAmount(id, transfers){
|
||||
return transfers
|
||||
.filter(t => t.returnValues.from === id)
|
||||
.reduce((pv, cv) => {
|
||||
@ -127,25 +127,27 @@ function getNumberOfBackers(pledges){
|
||||
return length(uniqBy(p => p.owner, pledges))
|
||||
}
|
||||
|
||||
async function getProjectAge(id, events, setState){
|
||||
async function _getProjectAge(id, events, setState){
|
||||
const event = events.find(e => e.returnValues.idProject === id)
|
||||
const { timestamp } = await web3.eth.getBlock(event.blockNumber)
|
||||
setState(timeSinceBlock(timestamp, 'days'))
|
||||
}
|
||||
|
||||
async function getProjectAssets(hash, setState){
|
||||
async function _getProjectAssets(hash, setState){
|
||||
console.log({hash})
|
||||
const CID = hash.split('/').slice(-1)[0]
|
||||
getFiles(CID)
|
||||
.then((files) => {
|
||||
setState(files)
|
||||
const manifest = files[2]
|
||||
console.log({files}, JSON.parse(manifest.content))
|
||||
})
|
||||
.catch(console.log)
|
||||
.then((files) => {
|
||||
setState(files)
|
||||
const manifest = files[2]
|
||||
console.log({files}, JSON.parse(manifest.content))
|
||||
})
|
||||
.catch(console.log)
|
||||
}
|
||||
|
||||
const getProjectManifest = assets => assets ? JSON.parse(assets.find(a => a.name.toLowerCase() === 'manifest.json').content) : null
|
||||
const getProjectManifest = assets => {
|
||||
return assets ? JSON.parse(assets.find(a => a.name.toLowerCase() === 'manifest.json').content) : null
|
||||
}
|
||||
|
||||
const formatMedia = content => {
|
||||
const type = 'video/mp4'
|
||||
@ -206,65 +208,65 @@ function Project({ classes, match, profile, transfers, pledges, projectAddedEven
|
||||
100
|
||||
) : 0
|
||||
console.log({profile, projectAssets, mediaUrl, mediaType, amountsPledged, pledges, transfers})
|
||||
return (
|
||||
!projectAssets
|
||||
? <Loading />
|
||||
:
|
||||
<div className={classes.root}>
|
||||
<div className={classes.creator}>
|
||||
<Avatar src={manifest && avatarUrl} />
|
||||
<Typography className={classes.creatorName}>{manifest && `By ${manifest.creator}`}</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography className={classes.title} component="h2" gutterBottom>
|
||||
{manifest && manifest.title}
|
||||
</Typography>
|
||||
<Typography className={classes.subTitle} component="h5" gutterBottom>
|
||||
{manifest && manifest.subtitle}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={classes.secondRow}>
|
||||
{mediaType
|
||||
? <ReactPlayer width="100%" height="100%" url={mediaUrl} playing={manifest.media.isPlaying} controls />
|
||||
: <CardMedia
|
||||
component="img"
|
||||
alt="video"
|
||||
className={classes.media}
|
||||
src={mediaUrl}
|
||||
title="media-description"
|
||||
/>}
|
||||
<div className={classes.infoBox}>
|
||||
{mediaUrl ? <LinearProgress
|
||||
classes={{
|
||||
colorPrimary: classes.linearColorPrimary,
|
||||
barColorPrimary: classes.linearBarColorPrimary,
|
||||
}}
|
||||
variant="determinate"
|
||||
value={percentToGoal}
|
||||
/> : <LinearProgress />}
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.raisedAmount}>
|
||||
{`${totalPledged.toLocaleString()} ${amountsPledged[0] ? amountsPledged[0][0] : ''}`}
|
||||
</span>
|
||||
<span className={classes.subtext}>{manifest && `pledged of ${Number(manifest.goal).toLocaleString()} goal`}</span>
|
||||
</div>
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.infoText}>{numberOfBackers}</span>
|
||||
<span className={classes.subtext}>backers</span>
|
||||
</div>
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.infoText}>{projectAge}</span>
|
||||
<span className={classes.subtext}>days active</span>
|
||||
</div>
|
||||
<div>
|
||||
<Link to={`/back-project/${projectId}`} className={classes.link}>
|
||||
<Button color="primary" variant="contained" style={{ height: '50px', width: '100%' }}>Back this project</Button>
|
||||
</Link>
|
||||
</div>
|
||||
return (<Fragment>
|
||||
{!projectAssets && <Loading/>}
|
||||
{projectAssets && <div className={classes.root}>
|
||||
<div className={classes.creator}>
|
||||
<Avatar src={manifest && avatarUrl}/>
|
||||
<Typography className={classes.creatorName}>{manifest && `By ${manifest.creator}`}</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography className={classes.title} component="h2" gutterBottom>
|
||||
{manifest && manifest.title}
|
||||
</Typography>
|
||||
<Typography className={classes.subTitle} component="h5" gutterBottom>
|
||||
{manifest && manifest.subtitle}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={classes.secondRow}>
|
||||
{mediaType &&
|
||||
<ReactPlayer width="100%" height="100%" url={mediaUrl} playing={manifest.media.isPlaying} controls/>}
|
||||
{!mediaType && <CardMedia
|
||||
component="img"
|
||||
alt="video"
|
||||
className={classes.media}
|
||||
src={mediaUrl}
|
||||
title="media-description"
|
||||
/>}
|
||||
<div className={classes.infoBox}>
|
||||
{mediaUrl ? <LinearProgress
|
||||
classes={{
|
||||
colorPrimary: classes.linearColorPrimary,
|
||||
barColorPrimary: classes.linearBarColorPrimary,
|
||||
}}
|
||||
variant="determinate"
|
||||
value={percentToGoal}
|
||||
/> : <LinearProgress/>}
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.raisedAmount}>
|
||||
{`${totalPledged.toLocaleString()} ${amountsPledged[0] ? amountsPledged[0][0] : ''}`}
|
||||
</span>
|
||||
<span
|
||||
className={classes.subtext}>{manifest && `pledged of ${Number(manifest.goal).toLocaleString()} goal`}</span>
|
||||
</div>
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.infoText}>{numberOfBackers}</span>
|
||||
<span className={classes.subtext}>backers</span>
|
||||
</div>
|
||||
<div className={classes.infoBoxSection}>
|
||||
<span className={classes.infoText}>{projectAge}</span>
|
||||
<span className={classes.subtext}>days active</span>
|
||||
</div>
|
||||
<div>
|
||||
<Link to={`/back-project/${projectId}`} className={classes.link}>
|
||||
<Button color="primary" variant="contained" style={{height: '50px', width: '100%'}}>Back this
|
||||
project</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
</div>}
|
||||
</Fragment>)
|
||||
}
|
||||
|
||||
Project.propTypes = {
|
@ -1,6 +1,6 @@
|
||||
/*global web3*/
|
||||
import EmbarkJS from 'Embark/EmbarkJS'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import EmbarkJS from '../../embarkArtifacts/embarkjs'
|
||||
import LiquidPledging from '../../embarkArtifacts/contracts/LiquidPledging'
|
||||
import { useState, useEffect, useMemo, useContext } from 'react'
|
||||
import { unnest } from 'ramda'
|
||||
import { timeSinceBlock } from '../../utils/dates'
|
||||
@ -17,7 +17,7 @@ async function getProjectAge(id, events, setState){
|
||||
}
|
||||
|
||||
async function getProjectAssets(projectId, setState){
|
||||
EmbarkJS.onReady(async (err) => {
|
||||
EmbarkJS.onReady(async (_err) => {
|
||||
const projectInfo = await LiquidPledging.methods.getPledgeAdmin(projectId).call()
|
||||
const CID = projectInfo.url.split('/').slice(-1)[0]
|
||||
console.log({CID, projectInfo, ipfs})
|
||||
@ -30,7 +30,7 @@ async function getProjectAssets(projectId, setState){
|
||||
.catch(async (err) => {
|
||||
console.log('IPFS getFiles error: ', err)
|
||||
databaseExists('ipfs')
|
||||
.catch(() => location.reload())
|
||||
.catch(() => window.location.reload())
|
||||
|
||||
getFiles(CID)
|
||||
.then((files) => {
|
||||
@ -77,7 +77,9 @@ export function useProfileData(profiles) {
|
||||
return delegatePledges
|
||||
}
|
||||
|
||||
const getProjectManifest = assets => assets ? JSON.parse(assets.find(a => a.name.toLowerCase() === 'manifest.json').content) : null
|
||||
const getProjectManifest = assets => {
|
||||
return assets ? JSON.parse(assets.find(a => a.name.toLowerCase() === 'manifest.json').content) : null
|
||||
}
|
||||
|
||||
export function useProjectData(projectId, profile, projectAddedEvents) {
|
||||
const [projectAge, setAge] = useState(null)
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { Formik } from 'formik'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LiquidPledging from '../../embarkArtifacts/contracts/LiquidPledging'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
@ -22,7 +22,7 @@ function TransferCard({ row, handleClose, classes }) {
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{}}
|
||||
onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => {
|
||||
onSubmit={async (values, { setSubmitting: _setSubmitting, resetForm, setStatus: _setStatus }) => {
|
||||
const { idPledge, pledge } = row
|
||||
const { idSender, amount, idReceiver } = values
|
||||
const args = [idSender, idPledge, toWei(amount.toString()), idReceiver]
|
||||
@ -55,15 +55,15 @@ function TransferCard({ row, handleClose, classes }) {
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
submitForm,
|
||||
setFieldValue,
|
||||
setStatus,
|
||||
status
|
||||
submitForm: _submitForm,
|
||||
setFieldValue: _setFieldValue,
|
||||
setStatus: _setStatus,
|
||||
status: _status
|
||||
}) => (
|
||||
<Collapse in={show} >
|
||||
<form onSubmit={handleSubmit} autoComplete="off">
|
@ -12,8 +12,8 @@ import Button from '@material-ui/core/Button'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Collapse from '@material-ui/core/Collapse'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LPVault from 'Embark/contracts/LPVault'
|
||||
import LiquidPledging from '../../embarkArtifacts/contracts/LiquidPledging'
|
||||
import LPVault from '../../embarkArtifacts/contracts/LPVault'
|
||||
import { getTokenLabel } from '../../utils/currencies'
|
||||
import { toWei } from '../../utils/conversions'
|
||||
import styles from './CardStyles'
|
||||
@ -28,7 +28,7 @@ function Withdraw({ handleClose, classes, rowData, authorizedPayment }) {
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{}}
|
||||
onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => {
|
||||
onSubmit={async (values, { setSubmitting: _setSubmitting, resetForm: _resetForm, setStatus: _setStatus }) => {
|
||||
const { amount } = values
|
||||
const paymentId = isPaying ? authorizedPayment[0]['returnValues']['idPayment'] : rowData.idPledge
|
||||
const args = isPaying ? [paymentId] : [paymentId, toWei(amount)]
|
||||
@ -54,14 +54,14 @@ function Withdraw({ handleClose, classes, rowData, authorizedPayment }) {
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
errors: _errors,
|
||||
touched: _touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue,
|
||||
setStatus,
|
||||
status
|
||||
setFieldValue: _setFieldValue,
|
||||
setStatus: _setStatus,
|
||||
status: _status
|
||||
}) => (
|
||||
<Collapse in={show}>
|
||||
<form autoComplete="off" onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', marginBottom: '0px' }}>
|
||||
@ -71,16 +71,16 @@ function Withdraw({ handleClose, classes, rowData, authorizedPayment }) {
|
||||
{`${isPaying ? 'Confirm' : ''} Withdraw${isPaying ? 'al' : ''} ${values.amount || ''} ${values.amount ? getTokenLabel(rowData.pledge.token) : ''} from Pledge ${rowData.idPledge}`}
|
||||
</Typography>
|
||||
{!isPaying && <TextField
|
||||
className={classes.amount}
|
||||
id="amount"
|
||||
name="amount"
|
||||
label="Amount"
|
||||
placeholder="Amount"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.amount || ''}
|
||||
className={classes.amount}
|
||||
id="amount"
|
||||
name="amount"
|
||||
label="Amount"
|
||||
placeholder="Amount"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.amount || ''}
|
||||
/>}
|
||||
</CardContent>
|
||||
<CardActions>
|
@ -1,8 +1,8 @@
|
||||
/*global web3*/
|
||||
import React from 'react'
|
||||
import { HashRouter as Router } from 'react-router-dom'
|
||||
import EmbarkJS from 'Embark/EmbarkJS'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import EmbarkJS from './embarkArtifacts/embarkjs'
|
||||
import LiquidPledging from './embarkArtifacts/contracts/LiquidPledging'
|
||||
import Snackbar from '@material-ui/core/Snackbar'
|
||||
import { initVaultAndLP, vaultPledgingNeedsInit, standardTokenApproval, getLpAllowance } from './utils/initialize'
|
||||
import { getAuthorizedPayments } from './utils/events'
|
||||
@ -26,10 +26,13 @@ class App extends React.Component {
|
||||
|
||||
componentDidMount(){
|
||||
EmbarkJS.onReady(async (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
getNetworkType().then(async network => {
|
||||
const { environment } = EmbarkJS
|
||||
const isInitialized = await vaultPledgingNeedsInit()
|
||||
if (!!isInitialized) {
|
||||
if (isInitialized) {
|
||||
if (environment === 'development') console.log('mock_time:', await LiquidPledging.mock_time.call())
|
||||
|
||||
const account = await web3.eth.getCoinbase()
|
||||
@ -73,9 +76,9 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, needsInit, loading, authorizedPayments, snackbar, network, environment } = this.state
|
||||
const { account, needsInit, lpAllowance: _lpAllowance, loading, authorizedPayments, snackbar } = this.state
|
||||
const { appendFundProfile, appendPledges, transferPledgeAmounts, openSnackBar, closeSnackBar } = this
|
||||
const fundingContext = { appendPledges, appendFundProfile, account, transferPledgeAmounts, authorizedPayments, needsInit, initVaultAndLP, standardTokenApproval, openSnackBar, closeSnackBar, network, environment }
|
||||
const fundingContext = { appendPledges, appendFundProfile, account, transferPledgeAmounts, authorizedPayments, needsInit, initVaultAndLP, standardTokenApproval, openSnackBar, closeSnackBar }
|
||||
return (
|
||||
<FundingContext.Provider value={fundingContext}>
|
||||
<Router>
|
@ -9,6 +9,7 @@ import Pledge from './model/pledge'
|
||||
import Delegate from './model/delegate'
|
||||
|
||||
const dbName = 'LiquidFunding'
|
||||
|
||||
const adapter = new LokiJSAdapter({
|
||||
dbName,
|
||||
schema,
|
@ -1,8 +1,10 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import DatabaseProvider from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import EmbarkJS from './embarkArtifacts/embarkjs'
|
||||
import database from './db';
|
||||
import App from './dapp';
|
||||
console.log(EmbarkJS);
|
||||
|
||||
render(
|
||||
<DatabaseProvider database={database}>
|
@ -17,7 +17,7 @@ export default class LpEvent extends Model {
|
||||
@json('return_values', sanitizeValues) returnValues
|
||||
|
||||
@action async addEvent(data) {
|
||||
return await this.create(lpEvent => {
|
||||
return this.create(lpEvent => {
|
||||
const { event, address, id, blockNumber } = data
|
||||
lpEvent.eventId = id
|
||||
lpEvent.address = address
|
@ -1,3 +1,4 @@
|
||||
/*global BigInt*/
|
||||
import { action, field, relation, json } from '@nozbe/watermelondb/decorators'
|
||||
import { Q } from '@nozbe/watermelondb'
|
||||
import { LiquidModel } from '../utils/models'
|
@ -1,3 +1,4 @@
|
||||
/*global BigInt*/
|
||||
import { createSelector } from 'reselect'
|
||||
import { toEther } from '../utils/conversions'
|
||||
import { getTokenLabel, getTokenAddress } from '../utils/currencies'
|
||||
@ -71,7 +72,7 @@ const formatAndSumDepositWithdraws = (deposits, pledges, withdraws) => {
|
||||
.entries(tokens)
|
||||
.forEach(token => {
|
||||
const [key, value] = token
|
||||
const address = getTokenAddress(key)
|
||||
const _address = getTokenAddress(key)
|
||||
tokens[key]['deposits'] = toEther(value['deposits'].toString())
|
||||
if (tokens[key]['withdraws']) tokens[key]['withdraws'] = toEther(value['withdraws'].toString())
|
||||
})
|
307
src/utils/colorSchemes.js
Normal file
307
src/utils/colorSchemes.js
Normal file
@ -0,0 +1,307 @@
|
||||
// examples: https://nagix.github.io/chartjs-plugin-colorschemes/
|
||||
export const colors = {
|
||||
// Sequential
|
||||
YlGn3: ['#f7fcb9', '#addd8e', '#31a354'],
|
||||
YlGn4: ['#ffffcc', '#c2e699', '#78c679', '#238443'],
|
||||
YlGn5: ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'],
|
||||
YlGn6: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#31a354', '#006837'],
|
||||
YlGn7: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'],
|
||||
YlGn8: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'],
|
||||
YlGn9: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'],
|
||||
|
||||
YlGnBu3: ['#edf8b1', '#7fcdbb', '#2c7fb8'],
|
||||
YlGnBu4: ['#ffffcc', '#a1dab4', '#41b6c4', '#225ea8'],
|
||||
YlGnBu5: ['#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494'],
|
||||
YlGnBu6: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#2c7fb8', '#253494'],
|
||||
YlGnBu7: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'],
|
||||
YlGnBu8: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'],
|
||||
YlGnBu9: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'],
|
||||
|
||||
GnBu3: ['#e0f3db', '#a8ddb5', '#43a2ca'],
|
||||
GnBu4: ['#f0f9e8', '#bae4bc', '#7bccc4', '#2b8cbe'],
|
||||
GnBu5: ['#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac'],
|
||||
GnBu6: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#43a2ca', '#0868ac'],
|
||||
GnBu7: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'],
|
||||
GnBu8: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'],
|
||||
GnBu9: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'],
|
||||
|
||||
BuGn3: ['#e5f5f9', '#99d8c9', '#2ca25f'],
|
||||
BuGn4: ['#edf8fb', '#b2e2e2', '#66c2a4', '#238b45'],
|
||||
BuGn5: ['#edf8fb', '#b2e2e2', '#66c2a4', '#2ca25f', '#006d2c'],
|
||||
BuGn6: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#2ca25f', '#006d2c'],
|
||||
BuGn7: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'],
|
||||
BuGn8: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'],
|
||||
BuGn9: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'],
|
||||
|
||||
PuBuGn3: ['#ece2f0', '#a6bddb', '#1c9099'],
|
||||
PuBuGn4: ['#f6eff7', '#bdc9e1', '#67a9cf', '#02818a'],
|
||||
PuBuGn5: ['#f6eff7', '#bdc9e1', '#67a9cf', '#1c9099', '#016c59'],
|
||||
PuBuGn6: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#1c9099', '#016c59'],
|
||||
PuBuGn7: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'],
|
||||
PuBuGn8: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'],
|
||||
PuBuGn9: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'],
|
||||
|
||||
PuBu3: ['#ece7f2', '#a6bddb', '#2b8cbe'],
|
||||
PuBu4: ['#f1eef6', '#bdc9e1', '#74a9cf', '#0570b0'],
|
||||
PuBu5: ['#f1eef6', '#bdc9e1', '#74a9cf', '#2b8cbe', '#045a8d'],
|
||||
PuBu6: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#2b8cbe', '#045a8d'],
|
||||
PuBu7: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'],
|
||||
PuBu8: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'],
|
||||
PuBu9: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'],
|
||||
|
||||
BuPu3: ['#e0ecf4', '#9ebcda', '#8856a7'],
|
||||
BuPu4: ['#edf8fb', '#b3cde3', '#8c96c6', '#88419d'],
|
||||
BuPu5: ['#edf8fb', '#b3cde3', '#8c96c6', '#8856a7', '#810f7c'],
|
||||
BuPu6: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8856a7', '#810f7c'],
|
||||
BuPu7: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'],
|
||||
BuPu8: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'],
|
||||
BuPu9: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'],
|
||||
|
||||
RdPu3: ['#fde0dd', '#fa9fb5', '#c51b8a'],
|
||||
RdPu4: ['#feebe2', '#fbb4b9', '#f768a1', '#ae017e'],
|
||||
RdPu5: ['#feebe2', '#fbb4b9', '#f768a1', '#c51b8a', '#7a0177'],
|
||||
RdPu6: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#c51b8a', '#7a0177'],
|
||||
RdPu7: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'],
|
||||
RdPu8: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'],
|
||||
RdPu9: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'],
|
||||
|
||||
PuRd3: ['#e7e1ef', '#c994c7', '#dd1c77'],
|
||||
PuRd4: ['#f1eef6', '#d7b5d8', '#df65b0', '#ce1256'],
|
||||
PuRd5: ['#f1eef6', '#d7b5d8', '#df65b0', '#dd1c77', '#980043'],
|
||||
PuRd6: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#dd1c77', '#980043'],
|
||||
PuRd7: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'],
|
||||
PuRd8: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'],
|
||||
PuRd9: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'],
|
||||
|
||||
OrRd3: ['#fee8c8', '#fdbb84', '#e34a33'],
|
||||
OrRd4: ['#fef0d9', '#fdcc8a', '#fc8d59', '#d7301f'],
|
||||
OrRd5: ['#fef0d9', '#fdcc8a', '#fc8d59', '#e34a33', '#b30000'],
|
||||
OrRd6: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#e34a33', '#b30000'],
|
||||
OrRd7: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'],
|
||||
OrRd8: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'],
|
||||
OrRd9: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],
|
||||
|
||||
YlOrRd3: ['#ffeda0', '#feb24c', '#f03b20'],
|
||||
YlOrRd4: ['#ffffb2', '#fecc5c', '#fd8d3c', '#e31a1c'],
|
||||
YlOrRd5: ['#ffffb2', '#fecc5c', '#fd8d3c', '#f03b20', '#bd0026'],
|
||||
YlOrRd6: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'],
|
||||
YlOrRd7: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'],
|
||||
YlOrRd8: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'],
|
||||
YlOrRd9: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],
|
||||
|
||||
YlOrBr3: ['#fff7bc', '#fec44f', '#d95f0e'],
|
||||
YlOrBr4: ['#ffffd4', '#fed98e', '#fe9929', '#cc4c02'],
|
||||
YlOrBr5: ['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'],
|
||||
YlOrBr6: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#d95f0e', '#993404'],
|
||||
YlOrBr7: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'],
|
||||
YlOrBr8: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'],
|
||||
YlOrBr9: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'],
|
||||
|
||||
Purples3: ['#efedf5', '#bcbddc', '#756bb1'],
|
||||
Purples4: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#6a51a3'],
|
||||
Purples5: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#756bb1', '#54278f'],
|
||||
Purples6: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f'],
|
||||
Purples7: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'],
|
||||
Purples8: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'],
|
||||
Purples9: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'],
|
||||
|
||||
Blues3: ['#deebf7', '#9ecae1', '#3182bd'],
|
||||
Blues4: ['#eff3ff', '#bdd7e7', '#6baed6', '#2171b5'],
|
||||
Blues5: ['#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'],
|
||||
Blues6: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#3182bd', '#08519c'],
|
||||
Blues7: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
|
||||
Blues8: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'],
|
||||
Blues9: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'],
|
||||
|
||||
Greens3: ['#e5f5e0', '#a1d99b', '#31a354'],
|
||||
Greens4: ['#edf8e9', '#bae4b3', '#74c476', '#238b45'],
|
||||
Greens5: ['#edf8e9', '#bae4b3', '#74c476', '#31a354', '#006d2c'],
|
||||
Greens6: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#31a354', '#006d2c'],
|
||||
Greens7: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'],
|
||||
Greens8: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'],
|
||||
Greens9: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'],
|
||||
|
||||
Oranges3: ['#fee6ce', '#fdae6b', '#e6550d'],
|
||||
Oranges4: ['#feedde', '#fdbe85', '#fd8d3c', '#d94701'],
|
||||
Oranges5: ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603'],
|
||||
Oranges6: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#e6550d', '#a63603'],
|
||||
Oranges7: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'],
|
||||
Oranges8: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'],
|
||||
Oranges9: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'],
|
||||
|
||||
Reds3: ['#fee0d2', '#fc9272', '#de2d26'],
|
||||
Reds4: ['#fee5d9', '#fcae91', '#fb6a4a', '#cb181d'],
|
||||
Reds5: ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15'],
|
||||
Reds6: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#de2d26', '#a50f15'],
|
||||
Reds7: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'],
|
||||
Reds8: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'],
|
||||
Reds9: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'],
|
||||
|
||||
Greys3: ['#f0f0f0', '#bdbdbd', '#636363'],
|
||||
Greys4: ['#f7f7f7', '#cccccc', '#969696', '#525252'],
|
||||
Greys5: ['#f7f7f7', '#cccccc', '#969696', '#636363', '#252525'],
|
||||
Greys6: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#636363', '#252525'],
|
||||
Greys7: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'],
|
||||
Greys8: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'],
|
||||
Greys9: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'],
|
||||
|
||||
// Diverging
|
||||
PuOr3: ['#f1a340', '#f7f7f7', '#998ec3'],
|
||||
PuOr4: ['#e66101', '#fdb863', '#b2abd2', '#5e3c99'],
|
||||
PuOr5: ['#e66101', '#fdb863', '#f7f7f7', '#b2abd2', '#5e3c99'],
|
||||
PuOr6: ['#b35806', '#f1a340', '#fee0b6', '#d8daeb', '#998ec3', '#542788'],
|
||||
PuOr7: ['#b35806', '#f1a340', '#fee0b6', '#f7f7f7', '#d8daeb', '#998ec3', '#542788'],
|
||||
PuOr8: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788'],
|
||||
PuOr9: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788'],
|
||||
PuOr10: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],
|
||||
PuOr11: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],
|
||||
|
||||
BrBG3: ['#d8b365', '#f5f5f5', '#5ab4ac'],
|
||||
BrBG4: ['#a6611a', '#dfc27d', '#80cdc1', '#018571'],
|
||||
BrBG5: ['#a6611a', '#dfc27d', '#f5f5f5', '#80cdc1', '#018571'],
|
||||
BrBG6: ['#8c510a', '#d8b365', '#f6e8c3', '#c7eae5', '#5ab4ac', '#01665e'],
|
||||
BrBG7: ['#8c510a', '#d8b365', '#f6e8c3', '#f5f5f5', '#c7eae5', '#5ab4ac', '#01665e'],
|
||||
BrBG8: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e'],
|
||||
BrBG9: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e'],
|
||||
BrBG10: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],
|
||||
BrBG11: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],
|
||||
|
||||
PRGn3: ['#af8dc3', '#f7f7f7', '#7fbf7b'],
|
||||
PRGn4: ['#7b3294', '#c2a5cf', '#a6dba0', '#008837'],
|
||||
PRGn5: ['#7b3294', '#c2a5cf', '#f7f7f7', '#a6dba0', '#008837'],
|
||||
PRGn6: ['#762a83', '#af8dc3', '#e7d4e8', '#d9f0d3', '#7fbf7b', '#1b7837'],
|
||||
PRGn7: ['#762a83', '#af8dc3', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#7fbf7b', '#1b7837'],
|
||||
PRGn8: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'],
|
||||
PRGn9: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'],
|
||||
PRGn10: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],
|
||||
PRGn11: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],
|
||||
|
||||
PiYG3: ['#e9a3c9', '#f7f7f7', '#a1d76a'],
|
||||
PiYG4: ['#d01c8b', '#f1b6da', '#b8e186', '#4dac26'],
|
||||
PiYG5: ['#d01c8b', '#f1b6da', '#f7f7f7', '#b8e186', '#4dac26'],
|
||||
PiYG6: ['#c51b7d', '#e9a3c9', '#fde0ef', '#e6f5d0', '#a1d76a', '#4d9221'],
|
||||
PiYG7: ['#c51b7d', '#e9a3c9', '#fde0ef', '#f7f7f7', '#e6f5d0', '#a1d76a', '#4d9221'],
|
||||
PiYG8: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'],
|
||||
PiYG9: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'],
|
||||
PiYG10: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],
|
||||
PiYG11: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],
|
||||
|
||||
RdBu3: ['#ef8a62', '#f7f7f7', '#67a9cf'],
|
||||
RdBu4: ['#ca0020', '#f4a582', '#92c5de', '#0571b0'],
|
||||
RdBu5: ['#ca0020', '#f4a582', '#f7f7f7', '#92c5de', '#0571b0'],
|
||||
RdBu6: ['#b2182b', '#ef8a62', '#fddbc7', '#d1e5f0', '#67a9cf', '#2166ac'],
|
||||
RdBu7: ['#b2182b', '#ef8a62', '#fddbc7', '#f7f7f7', '#d1e5f0', '#67a9cf', '#2166ac'],
|
||||
RdBu8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'],
|
||||
RdBu9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'],
|
||||
RdBu10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],
|
||||
RdBu11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],
|
||||
|
||||
RdGy3: ['#ef8a62', '#ffffff', '#999999'],
|
||||
RdGy4: ['#ca0020', '#f4a582', '#bababa', '#404040'],
|
||||
RdGy5: ['#ca0020', '#f4a582', '#ffffff', '#bababa', '#404040'],
|
||||
RdGy6: ['#b2182b', '#ef8a62', '#fddbc7', '#e0e0e0', '#999999', '#4d4d4d'],
|
||||
RdGy7: ['#b2182b', '#ef8a62', '#fddbc7', '#ffffff', '#e0e0e0', '#999999', '#4d4d4d'],
|
||||
RdGy8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'],
|
||||
RdGy9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'],
|
||||
RdGy10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],
|
||||
RdGy11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],
|
||||
|
||||
RdYlBu3: ['#fc8d59', '#ffffbf', '#91bfdb'],
|
||||
RdYlBu4: ['#d7191c', '#fdae61', '#abd9e9', '#2c7bb6'],
|
||||
RdYlBu5: ['#d7191c', '#fdae61', '#ffffbf', '#abd9e9', '#2c7bb6'],
|
||||
RdYlBu6: ['#d73027', '#fc8d59', '#fee090', '#e0f3f8', '#91bfdb', '#4575b4'],
|
||||
RdYlBu7: ['#d73027', '#fc8d59', '#fee090', '#ffffbf', '#e0f3f8', '#91bfdb', '#4575b4'],
|
||||
RdYlBu8: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'],
|
||||
RdYlBu9: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'],
|
||||
RdYlBu10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],
|
||||
RdYlBu11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],
|
||||
|
||||
Spectral3: ['#fc8d59', '#ffffbf', '#99d594'],
|
||||
Spectral4: ['#d7191c', '#fdae61', '#abdda4', '#2b83ba'],
|
||||
Spectral5: ['#d7191c', '#fdae61', '#ffffbf', '#abdda4', '#2b83ba'],
|
||||
Spectral6: ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd'],
|
||||
Spectral7: ['#d53e4f', '#fc8d59', '#fee08b', '#ffffbf', '#e6f598', '#99d594', '#3288bd'],
|
||||
Spectral8: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'],
|
||||
Spectral9: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'],
|
||||
Spectral10: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],
|
||||
Spectral11: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],
|
||||
|
||||
RdYlGn3: ['#fc8d59', '#ffffbf', '#91cf60'],
|
||||
RdYlGn4: ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'],
|
||||
RdYlGn5: ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641'],
|
||||
RdYlGn6: ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'],
|
||||
RdYlGn7: ['#d73027', '#fc8d59', '#fee08b', '#ffffbf', '#d9ef8b', '#91cf60', '#1a9850'],
|
||||
RdYlGn8: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'],
|
||||
RdYlGn9: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'],
|
||||
RdYlGn10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],
|
||||
RdYlGn11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],
|
||||
|
||||
// Qualitative
|
||||
Accent3: ['#7fc97f', '#beaed4', '#fdc086'],
|
||||
Accent4: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99'],
|
||||
Accent5: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0'],
|
||||
Accent6: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'],
|
||||
Accent7: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17'],
|
||||
Accent8: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'],
|
||||
|
||||
'Dark2-3': ['#1b9e77', '#d95f02', '#7570b3'],
|
||||
'Dark2-4': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a'],
|
||||
'Dark2-5': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e'],
|
||||
'Dark2-6': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02'],
|
||||
'Dark2-7': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d'],
|
||||
'Dark2-8': ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'],
|
||||
|
||||
Paired3: ['#a6cee3', '#1f78b4', '#b2df8a'],
|
||||
Paired4: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c'],
|
||||
Paired5: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99'],
|
||||
Paired6: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c'],
|
||||
Paired7: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f'],
|
||||
Paired8: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00'],
|
||||
Paired9: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6'],
|
||||
Paired10: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a'],
|
||||
Paired11: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99'],
|
||||
Paired12: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'],
|
||||
|
||||
'Pastel1-3': ['#fbb4ae', '#b3cde3', '#ccebc5'],
|
||||
'Pastel1-4': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4'],
|
||||
'Pastel1-5': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6'],
|
||||
'Pastel1-6': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc'],
|
||||
'Pastel1-7': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd'],
|
||||
'Pastel1-8': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec'],
|
||||
'Pastel1-9': ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'],
|
||||
|
||||
'Pastel2-3': ['#b3e2cd', '#fdcdac', '#cbd5e8'],
|
||||
'Pastel2-4': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4'],
|
||||
'Pastel2-5': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9'],
|
||||
'Pastel2-6': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae'],
|
||||
'Pastel2-7': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc'],
|
||||
'Pastel2-8': ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'],
|
||||
|
||||
'Set1-3': ['#e41a1c', '#377eb8', '#4daf4a'],
|
||||
'Set1-4': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3'],
|
||||
'Set1-5': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'],
|
||||
'Set1-6': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33'],
|
||||
'Set1-7': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628'],
|
||||
'Set1-8': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf'],
|
||||
'Set1-9': ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'],
|
||||
|
||||
'Set2-3': ['#66c2a5', '#fc8d62', '#8da0cb'],
|
||||
'Set2-4': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3'],
|
||||
'Set2-5': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854'],
|
||||
'Set2-6': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f'],
|
||||
'Set2-7': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494'],
|
||||
'Set2-8': ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'],
|
||||
|
||||
'Set3-3': ['#8dd3c7', '#ffffb3', '#bebada'],
|
||||
'Set3-4': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072'],
|
||||
'Set3-5': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'],
|
||||
'Set3-6': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462'],
|
||||
'Set3-7': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69'],
|
||||
'Set3-8': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5'],
|
||||
'Set3-9': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9'],
|
||||
'Set3-10': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd'],
|
||||
'Set3-11': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5'],
|
||||
'Set3-12': ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f']
|
||||
};
|
||||
|
||||
export const getColor = (pallet, idx) => colors[pallet][idx % colors[pallet].length]
|
@ -1,4 +1,4 @@
|
||||
import SNT from 'Embark/contracts/SNT'
|
||||
import SNT from '../embarkArtifacts/contracts/SNT'
|
||||
import sntIco from 'cryptocurrency-icons/svg/color/snt.svg'
|
||||
|
||||
export const TOKEN_ICON_API = 'https://raw.githubusercontent.com/TrustWallet/tokens/master/images'
|
||||
@ -31,6 +31,6 @@ export const getTokenLabel = value => {
|
||||
}
|
||||
|
||||
export const getTokenAddress = label => {
|
||||
const token = currencies.find(currency => currency.label == label)
|
||||
const token = currencies.find(currency => currency.label === label)
|
||||
return token ? token.value : null
|
||||
}
|
20
src/utils/dates.js
Normal file
20
src/utils/dates.js
Normal file
@ -0,0 +1,20 @@
|
||||
export function timeSinceBlock(date, interval) {
|
||||
var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7;
|
||||
let date1 = new Date(date*1000);
|
||||
let date2 = new Date();
|
||||
var timediff = date2 - date1;
|
||||
if (isNaN(timediff)) return NaN;
|
||||
switch (interval) {
|
||||
case 'years': return date2.getFullYear() - date1.getFullYear();
|
||||
case 'months': return (
|
||||
((date2.getFullYear() * 12) + date2.getMonth()) -
|
||||
((date1.getFullYear() * 12) + date1.getMonth())
|
||||
);
|
||||
case 'weeks': return Math.floor(timediff / week)
|
||||
case 'days': return Math.floor(timediff / day)
|
||||
case 'hours': return Math.floor(timediff / hour)
|
||||
case 'minutes': return Math.floor(timediff / minute)
|
||||
case 'seconds': return Math.floor(timediff / second)
|
||||
default: return undefined
|
||||
}
|
||||
}
|
@ -14,17 +14,16 @@ export function initialize(target, name, descriptor) {
|
||||
export function databaseExists(name){
|
||||
return new Promise(function(resolve, reject){
|
||||
var db = indexedDB,
|
||||
req;
|
||||
req;
|
||||
|
||||
try{
|
||||
// See if it exist
|
||||
req = db.webkitGetDatabaseNames();
|
||||
req.onsuccess = function(evt){
|
||||
~([].slice.call(evt.target.result)).indexOf(name) ?
|
||||
resolve(true):
|
||||
reject(false);
|
||||
req.onsuccess = function(evt) {
|
||||
// eslint-disable-next-line
|
||||
~([].slice.call(evt.target.result)).indexOf(name) ? resolve(true) : reject(new Error('unknown db'));
|
||||
}
|
||||
} catch (e){
|
||||
} catch (e) {
|
||||
// Try if it exist
|
||||
req = db.open(name);
|
||||
req.onsuccess = function () {
|
||||
@ -33,7 +32,7 @@ export function databaseExists(name){
|
||||
}
|
||||
req.onupgradeneeded = function (evt) {
|
||||
evt.target.transaction.abort();
|
||||
reject(false);
|
||||
reject(new Error('abort'));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*global web3*/
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import LPVault from 'Embark/contracts/LPVault'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import LPVault from '../embarkArtifacts/contracts/LPVault'
|
||||
|
||||
const AUTHORIZE_PAYMENT = 'AuthorizePayment'
|
||||
export const GIVER_ADDED = 'GiverAdded'
|
||||
@ -94,7 +94,7 @@ export const getAllLPEvents = async fromBlock => await getPastEvents(
|
||||
export const getAuthorizedPayments = async () => getPastVaultEvents(AUTHORIZE_PAYMENT)
|
||||
export const getAllVaultEvents = async (fromBlock = 0) => getPastVaultEvents(ALL_EVENTS,true, fromBlock)
|
||||
export const getProfileEvents = async () => {
|
||||
const [ funderProfiles, delegateProfiles, projectProfiles]
|
||||
= await Promise.all([getFunderProfiles(), getDelegateProfiles(), getProjectProfiles()])
|
||||
return [ ...funderProfiles, ...delegateProfiles, ...projectProfiles]
|
||||
const [funderProfiles, delegateProfiles, projectProfiles] =
|
||||
await Promise.all([getFunderProfiles(), getDelegateProfiles(), getProjectProfiles()])
|
||||
return [...funderProfiles, ...delegateProfiles, ...projectProfiles]
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*global web3*/
|
||||
import LPVault from 'Embark/contracts/LPVault'
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
import SNT from 'Embark/contracts/SNT'
|
||||
import LPVault from '../embarkArtifacts/contracts/LPVault'
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
import SNT from '../embarkArtifacts/contracts/SNT'
|
||||
|
||||
export const initVaultAndLP = async () => {
|
||||
let estimateGas;
|
||||
@ -20,8 +20,8 @@ export const initVaultAndLP = async () => {
|
||||
}
|
||||
|
||||
export const vaultPledgingNeedsInit = async () => {
|
||||
const needsInit = !!Number(await LiquidPledging.methods.getInitializationBlock().call())
|
||||
&& !!Number(await LPVault.methods.getInitializationBlock().call())
|
||||
const needsInit = !!Number(await LiquidPledging.methods.getInitializationBlock().call()) &&
|
||||
!!Number(await LPVault.methods.getInitializationBlock().call())
|
||||
return needsInit
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ export const isIpfs = str => ipfsMatcher.test(str)
|
||||
export const captureFile = (event, cb, imgCb) => {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
const file = event.target.files[0]
|
||||
const files = event.target.files
|
||||
const formattedFiles = formatFileList(files)
|
||||
console.log({files, formattedFiles})
|
||||
@ -30,7 +29,7 @@ export const formatFileList = files => {
|
||||
}
|
||||
|
||||
export const formatForIpfs = file => {
|
||||
const { name, type } = file
|
||||
const { name, type: _type } = file
|
||||
const content = fileReaderPullStream(file)
|
||||
return {
|
||||
path: `/root/${name}`,
|
||||
@ -65,7 +64,7 @@ export const getFromIpfs = async hash => {
|
||||
const file = files.slice(-1)[0]
|
||||
const { content } = file
|
||||
const arrayBufferView = new Uint8Array(content)
|
||||
const blob = new Blob([ arrayBufferView ], { type: getImageType(file) })
|
||||
const blob = new Blob([arrayBufferView], { type: getImageType(file) })
|
||||
const img = URL.createObjectURL(blob)
|
||||
return { ...file, img }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*global web3*/
|
||||
import LiquidPledging from 'Embark/contracts/LiquidPledging'
|
||||
/*global web3, BigInt*/
|
||||
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||
|
||||
const { getPledgeDelegate, numberOfPledges, getPledge } = LiquidPledging.methods
|
||||
const getPledgeDelegates = (idPledge, numDelegates) => {
|
||||
@ -30,7 +30,7 @@ export const getAllPledges = async (start = 1) => {
|
||||
for (let i = start; i <= numPledges; i++) {
|
||||
pledges.push(getPledge(i).call())
|
||||
}
|
||||
return Promise.all(pledges.map(formatPledge))
|
||||
return Promise.all(pledges.map(formatPledge))
|
||||
}
|
||||
|
||||
export const getPledges = async (pledges = []) => {
|
||||
@ -59,7 +59,7 @@ export const appendToExistingPledges = async (pledges, setState) => {
|
||||
export const transferBetweenPledges = (setState, tx) => {
|
||||
const { from, to, amount } = tx
|
||||
setState((state) => {
|
||||
const { allPledges } = state;
|
||||
const { allPledges } = state
|
||||
const updatedPledges = allPledges.map(pledge => {
|
||||
if (pledge.id === Number(from)) {
|
||||
pledge.amount = (BigInt(pledge.amount) - BigInt(amount)).toString()
|
||||
@ -74,7 +74,7 @@ export const transferBetweenPledges = (setState, tx) => {
|
||||
console.log({updatedPledges, tx})
|
||||
return {
|
||||
...state,
|
||||
allPledges: [ ...updatedPledges ]
|
||||
allPledges: [...updatedPledges]
|
||||
}
|
||||
})
|
||||
}
|
@ -1,289 +0,0 @@
|
||||
/* global __dirname module process require */
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const dappPath = process.env.DAPP_PATH;
|
||||
const embarkPath = process.env.EMBARK_PATH;
|
||||
|
||||
const dappNodeModules = path.join(dappPath, 'node_modules');
|
||||
const embarkNodeModules = path.join(embarkPath, 'node_modules');
|
||||
let nodePathNodeModules;
|
||||
if (process.env.NODE_PATH) {
|
||||
nodePathNodeModules = process.env.NODE_PATH.split(path.delimiter);
|
||||
} else {
|
||||
nodePathNodeModules = [];
|
||||
}
|
||||
if (!nodePathNodeModules.includes(embarkNodeModules)) {
|
||||
nodePathNodeModules.unshift(embarkNodeModules);
|
||||
}
|
||||
|
||||
function requireFromEmbark(mod) {
|
||||
return require(requireFromEmbark.resolve(mod));
|
||||
}
|
||||
|
||||
requireFromEmbark.resolve = function (mod) {
|
||||
return require.resolve(
|
||||
mod,
|
||||
{paths: [embarkNodeModules]}
|
||||
);
|
||||
};
|
||||
|
||||
const cloneDeep = requireFromEmbark('lodash.clonedeep');
|
||||
const glob = requireFromEmbark('glob');
|
||||
const HardSourceWebpackPlugin = requireFromEmbark('hard-source-webpack-plugin');
|
||||
|
||||
const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json'));
|
||||
const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json'));
|
||||
const embarkJson = require(path.join(dappPath, 'embark.json'));
|
||||
const embarkPipeline = require(path.join(dappPath, '.embark/embark-pipeline.json'));
|
||||
|
||||
const buildDir = path.join(dappPath, embarkJson.buildDir);
|
||||
|
||||
// it's important to `embark reset` if a pkg version is specified in
|
||||
// embark.json and changed/removed later, otherwise pkg resolution may behave
|
||||
// unexpectedly
|
||||
let versions;
|
||||
try {
|
||||
versions = glob.sync(path.join(dappPath, '.embark/versions/*/*'));
|
||||
} catch (e) {
|
||||
versions = [];
|
||||
}
|
||||
|
||||
const entry = Object.keys(embarkAssets)
|
||||
.filter(key => key.match(/\.js$/))
|
||||
.reduce((obj, key) => {
|
||||
// webpack entry paths should start with './' if they're relative to the
|
||||
// webpack context; embark.json "app" keys correspond to lists of .js
|
||||
// source paths relative to the top-level dapp dir and may be missing the
|
||||
// leading './'
|
||||
obj[key] = embarkAssets[key]
|
||||
.map(file => {
|
||||
let file_path = file.path;
|
||||
if (!file.path.match(/^\.\//)) {
|
||||
file_path = './' + file_path;
|
||||
}
|
||||
return file_path;
|
||||
});
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
function resolve(pkgName) {
|
||||
if (Array.isArray(pkgName)) {
|
||||
const _pkgName = pkgName[0];
|
||||
pkgName[0] = requireFromEmbark.resolve(_pkgName);
|
||||
return pkgName;
|
||||
}
|
||||
return requireFromEmbark.resolve(pkgName);
|
||||
}
|
||||
|
||||
// base config
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// order and options of babel plugins and presets adapted from babel-preset-react-app:
|
||||
// see: https://github.com/facebook/create-react-app/tree/v2.0.4/packages/babel-preset-react-app
|
||||
// + babel plugins run before babel presets.
|
||||
// + babel plugin ordering is first to last.
|
||||
// + babel preset ordering is reversed (last to first).
|
||||
// see: https://babeljs.io/docs/en/plugins#plugin-ordering
|
||||
|
||||
const base = {
|
||||
context: dappPath,
|
||||
entry: entry,
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader',
|
||||
'sass-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
|
||||
loader: 'url-loader?limit=100000'
|
||||
},
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /(node_modules|bower_components|\.embark[\\/]versions)/,
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
customize: path.join(__dirname, 'babel-loader-overrides.js'),
|
||||
plugins: [
|
||||
[
|
||||
'babel-plugin-module-resolver', {
|
||||
alias: embarkAliases
|
||||
}
|
||||
],
|
||||
'babel-plugin-macros',
|
||||
'@babel/plugin-transform-destructuring',
|
||||
[
|
||||
'@babel/plugin-proposal-decorators', {
|
||||
legacy: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-proposal-class-properties', {
|
||||
loose: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-proposal-object-rest-spread', {
|
||||
useBuiltIns: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-transform-runtime', {
|
||||
helpers: true,
|
||||
regenerator: true
|
||||
}
|
||||
],
|
||||
'@babel/plugin-syntax-dynamic-import'
|
||||
].map(resolve),
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env', {
|
||||
exclude: ['transform-typeof-symbol'],
|
||||
modules: false,
|
||||
targets: {
|
||||
browsers: ['last 1 version', 'not dead', '> 0.2%']
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/preset-react', {
|
||||
useBuiltIns: true
|
||||
}
|
||||
]
|
||||
].map(resolve)
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
use: { loader: 'worker-loader' }
|
||||
}
|
||||
]
|
||||
},
|
||||
output: {
|
||||
filename: (chunkData) => chunkData.chunk.name,
|
||||
// globalObject workaround for node-compatible UMD builds with webpack 4
|
||||
// see: https://github.com/webpack/webpack/issues/6522#issuecomment-371120689
|
||||
// see: https://github.com/webpack/webpack/issues/6522#issuecomment-418864518
|
||||
globalObject: '(typeof self !== \'undefined\' ? self : this)',
|
||||
libraryTarget: 'umd',
|
||||
path: buildDir
|
||||
},
|
||||
plugins: [new HardSourceWebpackPlugin()],
|
||||
// profiling and generating verbose stats increases build time; if stats
|
||||
// are generated embark will write the output to:
|
||||
// path.join(dappPath, '.embark/stats.[json,report]')
|
||||
// to visualize the stats info in a browser run:
|
||||
// npx webpack-bundle-analyzer .embark/stats.json <buildDir>
|
||||
profile: true, stats: 'verbose',
|
||||
resolve: {
|
||||
alias: embarkAliases,
|
||||
extensions: [
|
||||
// webpack defaults
|
||||
// see: https://webpack.js.org/configuration/resolve/#resolve-extensions
|
||||
'.wasm', '.mjs', '.js', '.json',
|
||||
// additional extensions
|
||||
'.jsx'
|
||||
],
|
||||
modules: [
|
||||
...versions,
|
||||
'node_modules',
|
||||
dappNodeModules,
|
||||
...nodePathNodeModules
|
||||
]
|
||||
},
|
||||
resolveLoader: {
|
||||
modules: [
|
||||
'node_modules',
|
||||
dappNodeModules,
|
||||
...nodePathNodeModules
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const baseBabelLoader = base.module.rules[3];
|
||||
|
||||
// Flow
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// should be false in configs that have isTypeScriptEnabled = true
|
||||
// const isFlowEnabled = !embarkPipeline.typescript;
|
||||
// if (isFlowEnabled) {
|
||||
// // position @babel/plugin-transform-flow-strip-types per babel-preset-react-app
|
||||
// baseBabelLoader.options.plugins.unshift(
|
||||
// requireFromEmbark.resolve('@babel/plugin-transform-flow-strip-types')
|
||||
// );
|
||||
// }
|
||||
|
||||
// TypeScript
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// should be false in configs that have isFlowEnabled = true
|
||||
const isTypeScriptEnabled = !!embarkPipeline.typescript;
|
||||
if (isTypeScriptEnabled) {
|
||||
// position @babel/preset-typescript as the last preset (runs first)
|
||||
// see: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/
|
||||
baseBabelLoader.options.presets.push(
|
||||
requireFromEmbark.resolve('@babel/preset-typescript')
|
||||
);
|
||||
// additional extensions
|
||||
baseBabelLoader.test = /\.(js|ts)x?$/;
|
||||
base.resolve.extensions.push('.ts', '.tsx');
|
||||
}
|
||||
|
||||
// if (isFlowEnabled && isTypeScriptEnabled) {
|
||||
// throw new Error('isFlowEnabled and isTypeScriptEnabled cannot both be true');
|
||||
// }
|
||||
|
||||
// development config
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const development = cloneDeep(base);
|
||||
// full source maps increase build time but are useful during dapp development
|
||||
development.devtool = 'source-map';
|
||||
development.mode = 'development';
|
||||
// alternatively:
|
||||
// development.mode = 'none';
|
||||
development.name = 'development';
|
||||
const devBabelLoader = development.module.rules[3];
|
||||
devBabelLoader.options.compact = false;
|
||||
// enable 'development' option for @babel/preset-react
|
||||
const devPresetReact = devBabelLoader.options.presets[1];
|
||||
const devPresetReactOptions = devPresetReact[1];
|
||||
devPresetReactOptions.development = true;
|
||||
|
||||
// production config
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const production = cloneDeep(base);
|
||||
production.mode = 'production';
|
||||
production.name = 'production';
|
||||
const prodBabelLoader = production.module.rules[3];
|
||||
// position babel-plugin-transform-react-remove-prop-types per babel-preset-react-app
|
||||
prodBabelLoader.options.plugins.splice(prodBabelLoader.length - 1, 0, [
|
||||
requireFromEmbark.resolve('babel-plugin-transform-react-remove-prop-types'),
|
||||
{
|
||||
removeImport: true
|
||||
}
|
||||
]);
|
||||
|
||||
// export a list of named configs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
module.exports = [
|
||||
development,
|
||||
production
|
||||
];
|
Loading…
x
Reference in New Issue
Block a user