diff --git a/package-lock.json b/package-lock.json
index df47f29df..55bcf838a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5488,6 +5488,11 @@
"resolved": "https://registry.npmjs.org/final-form-calculate/-/final-form-calculate-1.1.0.tgz",
"integrity": "sha512-a5GIFDn7KEejkamxS/npZysmfvNKt9WfqqmDJRewwRkooOD4icVvB1Plpnkx4MGhgWAN6pg0yTjH002fQppGlg=="
},
+ "final-form-set-field-touched": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/final-form-set-field-touched/-/final-form-set-field-touched-1.0.0.tgz",
+ "integrity": "sha512-HybhN2L7EbEHxIOHxHuniAUZJmUqPJhJ8/a0fZADFNm969N6JZnk9LYKW+SU7Ni5Gddpj2xx1sWAMBfr7FGBCg=="
+ },
"finalhandler": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
diff --git a/package.json b/package.json
index dd91e847a..d0a300d38 100755
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
"final-form": "^4.3.1",
"final-form-arrays": "^1.0.4",
"final-form-calculate": "^1.1.0",
+ "final-form-set-field-touched": "^1.0.0",
"font-awesome": "^4.7.0",
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
diff --git a/src/App.js b/src/App.js
index f98b5612a..7e6c669cb 100644
--- a/src/App.js
+++ b/src/App.js
@@ -16,11 +16,10 @@ import {
} from './components/index'
import NoWeb3 from './components/Common/NoWeb3'
import IncompleteDeploy from './components/IncompleteDeploy'
-import { getQueryVariable } from './utils/utils'
+import { getAddr, toast } from './utils/utils'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import AlertContainer from 'react-alert'
import { TOAST } from './utils/constants'
-import { toast } from './utils/utils'
import { Web3Provider } from './react-web3'
@inject('deploymentStore')
@@ -28,7 +27,7 @@ import { Web3Provider } from './react-web3'
class App extends Component {
render() {
const { deploymentStore } = this.props
- var crowdsaleAddr = getQueryVariable('addr')
+ let crowdsaleAddr = getAddr()
return (
diff --git a/src/components/Common/ButtonContinue.js b/src/components/Common/ButtonContinue.js
new file mode 100644
index 000000000..c8d9a5ed3
--- /dev/null
+++ b/src/components/Common/ButtonContinue.js
@@ -0,0 +1,21 @@
+import React, { Component } from 'react'
+import classNames from 'classnames'
+
+export class ButtonContinue extends Component {
+ /**
+ * Render method for ButtonContinue component
+ * @returns {*}
+ */
+ render() {
+ const { status, type } = this.props
+ const submitButtonClass = classNames('button', 'button_fill', 'button_no_border', {
+ button_disabled: !status
+ })
+
+ return (
+
+ )
+ }
+}
diff --git a/src/components/Home/index.js b/src/components/Home/index.js
index 8ddcba045..69635501a 100644
--- a/src/components/Home/index.js
+++ b/src/components/Home/index.js
@@ -1,6 +1,5 @@
import React, { Component } from 'react'
import '../../assets/stylesheets/application.css'
-import { Link } from 'react-router-dom'
import CrowdsalesList from '../Common/CrowdsalesList'
import { Loader } from '../Common/Loader'
import { loadRegistryAddresses } from '../../utils/blockchainHelpers'
@@ -11,74 +10,132 @@ import { inject, observer } from 'mobx-react'
import { checkWeb3, getNetworkVersion } from '../../utils/blockchainHelpers'
import { getCrowdsaleAssets } from '../../stores/utils'
import logdown from 'logdown'
+import storage from 'store2'
const logger = logdown('TW:home')
const { CROWDSALE_STRATEGY, TOKEN_SETUP, CROWDSALE_SETUP, PUBLISH, CROWDSALE_PAGE } = NAVIGATION_STEPS
-@inject('web3Store', 'generalStore', 'contractStore')
+@inject(
+ 'web3Store',
+ 'generalStore',
+ 'contractStore',
+ 'crowdsaleStore',
+ 'gasPriceStore',
+ 'deploymentStore',
+ 'reservedTokenStore',
+ 'stepTwoValidationStore',
+ 'tierStore',
+ 'tokenStore'
+)
@observer
export class Home extends Component {
+ state = {
+ showModal: false,
+ loading: false
+ }
+
constructor(props) {
super(props)
- this.state = {
- showModal: false,
- loading: false
- }
let { contractStore } = this.props
contractStore.setProperty('downloadStatus', DOWNLOAD_STATUS.PENDING)
}
- componentDidMount() {
- let { generalStore, web3Store, contractStore } = this.props
- checkWeb3(web3Store.web3)
-
- getNetworkVersion()
- .then(networkID => {
- generalStore.setProperty('networkID', networkID)
- getCrowdsaleAssets(networkID)
- })
- .then(
- () => {
- contractStore.setProperty('downloadStatus', DOWNLOAD_STATUS.SUCCESS)
- },
- e => {
- logger.error('Error downloading contracts', e)
- toast.showToaster({
- type: TOAST.TYPE.ERROR,
- message:
- 'The contracts could not be downloaded.Please try to refresh the page. If the problem persists, try again later.'
- })
-
- contractStore.setProperty('downloadStatus', DOWNLOAD_STATUS.FAILURE)
- }
- )
+ async componentDidMount() {
+ let { web3Store } = this.props
+ await checkWeb3(web3Store.web3)
}
- chooseContract = () => {
+ chooseContract = async () => {
this.setState({
loading: true
})
- loadRegistryAddresses().then(
- () => {
- this.setState({
- loading: false,
- showModal: true
- })
- },
- e => {
- logger.error('There was a problem loading the crowdsale addresses from the registry', e)
- this.setState({
- loading: false
- })
+ try {
+ await loadRegistryAddresses()
+ this.setState({
+ loading: false,
+ showModal: true
+ })
+ } catch (e) {
+ logger.error('There was a problem loading the crowdsale addresses from the registry', e)
+ this.setState({
+ loading: false
+ })
+ }
+ }
+
+ goNextStep = async () => {
+ // Clear local storage if there is no incomplete deployment, and reload
+ if (storage.has('DeploymentStore') && storage.get('DeploymentStore').deploymentStep) {
+ this.props.history.push('/')
+ } else {
+ this.clearStorage()
+ await this.reloadStorage()
+ this.props.history.push('1')
+ }
+ }
+
+ async reloadStorage() {
+ let { generalStore, contractStore } = this.props
+
+ try {
+ // General store, check network
+ let networkID = await getNetworkVersion()
+ generalStore.setProperty('networkID', networkID)
+
+ // Contract store, get contract and abi
+ await getCrowdsaleAssets(networkID)
+ contractStore.setProperty('downloadStatus', DOWNLOAD_STATUS.SUCCESS)
+ } catch (e) {
+ logger.error('Error downloading contracts', e)
+ toast.showToaster({
+ type: TOAST.TYPE.ERROR,
+ message:
+ 'The contracts could not be downloaded.Please try to refresh the page. If the problem persists, try again later.'
+ })
+ contractStore.setProperty('downloadStatus', DOWNLOAD_STATUS.FAILURE)
+ }
+ }
+
+ clearStorage() {
+ // Generate of stores to clear
+ const toArray = ({
+ generalStore,
+ contractStore,
+ crowdsaleStore,
+ gasPriceStore,
+ deploymentStore,
+ reservedTokenStore,
+ stepTwoValidationStore,
+ tierStore,
+ tokenStore
+ }) => {
+ return [
+ generalStore,
+ contractStore,
+ crowdsaleStore,
+ gasPriceStore,
+ deploymentStore,
+ reservedTokenStore,
+ stepTwoValidationStore,
+ tierStore,
+ tokenStore
+ ]
+ }
+
+ const storesToClear = toArray(this.props)
+ for (let storeToClear of storesToClear) {
+ if (typeof storeToClear.reset === 'function') {
+ logger.log('Store to be cleared:', storeToClear.constructor.name)
+ storeToClear.reset()
}
- )
+ }
}
onClick = crowdsaleAddress => {
- this.props.history.push('/manage/' + crowdsaleAddress)
+ this.props.history.push(`manage/${crowdsaleAddress}`)
}
hideModal = () => {
@@ -99,9 +156,9 @@ export class Home extends Component {
Token Wizard is powered by Auth-os.
-
-
New crowdsale
-
+
this.chooseContract()} className="button button_outline">
Choose Crowdsale
diff --git a/src/components/stepOne/index.js b/src/components/stepOne/index.js
index 3c5a6ec89..9d9c07474 100644
--- a/src/components/stepOne/index.js
+++ b/src/components/stepOne/index.js
@@ -1,44 +1,72 @@
-import React from 'react'
+import React, { Component } from 'react'
import '../../assets/stylesheets/application.css'
import { Link } from 'react-router-dom'
import { StepNavigation } from '../Common/StepNavigation'
+import { inject, observer } from 'mobx-react'
+import { ButtonContinue } from '../Common/ButtonContinue'
+import { checkWeb3 } from '../../utils/blockchainHelpers'
import {
NAVIGATION_STEPS,
CROWDSALE_STRATEGIES,
CROWDSALE_STRATEGIES_DISPLAYNAMES,
DOWNLOAD_STATUS
} from '../../utils/constants'
-import { inject, observer } from 'mobx-react'
-import classNames from 'classnames'
import logdown from 'logdown'
+import { Loader } from '../Common/Loader'
-const logger = logdown('TW:components:stepOne')
+const logger = logdown('TW:stepOne')
const { CROWDSALE_STRATEGY } = NAVIGATION_STEPS
+const { MINTED_CAPPED_CROWDSALE, DUTCH_AUCTION } = CROWDSALE_STRATEGIES
-@inject('crowdsaleStore', 'contractStore')
+@inject('crowdsaleStore', 'contractStore', 'web3Store')
@observer
-export class stepOne extends React.Component {
- constructor(props) {
- super(props)
-
- this.setStrategy(null, CROWDSALE_STRATEGIES.MINTED_CAPPED_CROWDSALE)
+export class stepOne extends Component {
+ state = {
+ loading: false,
+ strategy: null
}
- setStrategy = (event, strategy) => {
- if (!strategy) {
- strategy = event.target.id
+ async componentDidMount() {
+ const { crowdsaleStore, web3Store } = this.props
+ await checkWeb3(web3Store.web3)
+
+ this.setState({ loading: true })
+ logger.log('CrowdsaleStore strategy', crowdsaleStore.strategy)
+
+ // Set default value
+ if (crowdsaleStore && !crowdsaleStore.strategy) {
+ crowdsaleStore.setProperty('strategy', MINTED_CAPPED_CROWDSALE)
}
- this.props.crowdsaleStore.setProperty('strategy', strategy)
+
+ this.setState({
+ loading: false,
+ strategy: crowdsaleStore.strategy
+ })
+ }
+
+ /**
+ * Handle radio input and set value for strategy
+ * @param e
+ */
+ handleChange = e => {
+ const { crowdsaleStore } = this.props
+ const strategy = e.currentTarget.value
+
+ crowdsaleStore.setProperty('strategy', strategy)
+ this.setState({
+ strategy: crowdsaleStore.strategy
+ })
+ logger.log('CrowdsaleStore strategy selected:', strategy)
}
+ /**
+ * Render method for stepOne component
+ * @returns {*}
+ */
render() {
const { contractStore } = this.props
- let status = contractStore.downloadStatus === DOWNLOAD_STATUS.SUCCESS && localStorage.length > 0
- logger.log('Contract store status', status)
- const submitButtonClass = classNames('button', 'button_fill', 'button_no_border', {
- button_disabled: !status
- })
+ let status = (contractStore && contractStore.downloadStatus === DOWNLOAD_STATUS.SUCCESS) || localStorage.length > 0
return (
@@ -49,13 +77,15 @@ export class stepOne extends React.Component {
{CROWDSALE_STRATEGY}
Select a strategy for your crowdsale.
-
+
@@ -71,11 +108,10 @@ export class stepOne extends React.Component {
-
+
+
)
}
diff --git a/src/components/stepTwo/StepTwoForm.js b/src/components/stepTwo/StepTwoForm.js
index 9bd0801b9..7884a89f4 100644
--- a/src/components/stepTwo/StepTwoForm.js
+++ b/src/components/stepTwo/StepTwoForm.js
@@ -6,7 +6,7 @@ import { TokenDecimals } from '../Common/TokenDecimals'
import { TokenSupply } from '../Common/TokenSupply'
import { ReservedTokensInputBlock } from '../Common/ReservedTokensInputBlock'
import { CROWDSALE_STRATEGIES } from '../../utils/constants'
-import classNames from 'classnames'
+import { ButtonContinue } from '../Common/ButtonContinue'
const errorStyle = {
color: 'red',
@@ -30,12 +30,12 @@ export const StepTwoForm = ({
crowdsaleStore,
invalid,
pristine,
- submitting
+ submitting,
+ mutators: { setFieldTouched },
+ reload,
+ form
}) => {
- // Build disable class to use in the submit button
- const submitButtonClass = classNames('button', 'button_fill', 'button_no_border', {
- button_disabled: submitting || pristine || invalid
- })
+ const status = !(submitting || invalid)
const reservedTokens = (
@@ -53,6 +53,20 @@ export const StepTwoForm = ({
)
+ const setFieldAsTouched = ({ values, errors }) => {
+ if (reload) {
+ form.mutators.setFieldTouched('name', true)
+ form.mutators.setFieldTouched('ticker', true)
+ form.mutators.setFieldTouched('decimals', true)
+ form.mutators.setFieldTouched('supply', true)
+ }
+ }
+
+ const onChangeForm = ({ values, errors }) => {
+ updateTokenStore({ values, errors })
+ setFieldAsTouched({ values, errors })
+ }
+
return (