Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Add store for dapps state (#3211)
Browse files Browse the repository at this point in the history
* Add mobx

* Use mobx store for dapps

* Cleanup hidden reads

* Remove (now) unused hidden.js

* _ denotes internal functions

* s/visibleApps/visible/

* AddDapps now use the mobx store as well

* Move modalOpen state to store

* Simplify

* Complete master merge

* Remove extra indirection

* Remove unneeded check

* Readability improvements

* Remove final debug info
  • Loading branch information
jacogr authored and arkpar committed Nov 7, 2016
1 parent f90f511 commit 34998a7
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 357 deletions.
5 changes: 4 additions & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"devDependencies": {
"babel-cli": "^6.10.1",
"babel-core": "^6.10.4",
"babel-eslint": "^6.1.2",
"babel-eslint": "^7.1.0",
"babel-loader": "^6.2.3",
"babel-plugin-lodash": "^3.2.2",
"babel-plugin-transform-class-properties": "^6.11.5",
Expand Down Expand Up @@ -126,6 +126,9 @@
"marked": "^0.3.6",
"material-ui": "^0.16.1",
"material-ui-chip-input": "^0.8.0",
"mobx": "^2.6.1",
"mobx-react": "^3.5.8",
"mobx-react-devtools": "^4.2.9",
"moment": "^2.14.1",
"qs": "^6.3.0",
"react": "^15.2.1",
Expand Down
42 changes: 6 additions & 36 deletions js/src/views/Dapp/dapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react';

import Contracts from '../../contracts';
import { fetchAvailable } from '../Dapps/registry';
import DappsStore from '../Dapps/dappsStore';

import styles from './dapp.css';

@observer
export default class Dapp extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
Expand All @@ -30,17 +31,12 @@ export default class Dapp extends Component {
params: PropTypes.object
};

state = {
app: null
}

componentWillMount () {
this.lookup();
}
store = new DappsStore(this.context.api);

render () {
const { app } = this.state;
const { dappsUrl } = this.context.api;
const { id } = this.props.params;
const app = this.store.apps.find((app) => app.id === id);

if (!app) {
return null;
Expand Down Expand Up @@ -76,30 +72,4 @@ export default class Dapp extends Component {
</iframe>
);
}

lookup () {
const { api } = this.context;
const { id } = this.props.params;
const { dappReg } = Contracts.get();

fetchAvailable(api)
.then((available) => {
return available.find((app) => app.id === id);
})
.then((app) => {
if (app.type !== 'network') {
return app;
}

return dappReg
.getContent(app.id)
.then((contentHash) => {
app.contentHash = api.util.bytesToHex(contentHash).substr(2);
return app;
});
})
.then((app) => {
this.setState({ app });
});
}
}
53 changes: 32 additions & 21 deletions js/src/views/Dapps/AddDapps/AddDapps.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react';
import DoneIcon from 'material-ui/svg-icons/action/done';
import { List, ListItem } from 'material-ui/List';
import Checkbox from 'material-ui/Checkbox';
Expand All @@ -23,57 +24,67 @@ import { Modal, Button } from '../../../ui';

import styles from './AddDapps.css';

@observer
export default class AddDapps extends Component {
static propTypes = {
available: PropTypes.array.isRequired,
hidden: PropTypes.array.isRequired,
open: PropTypes.bool.isRequired,
onHideApp: PropTypes.func.isRequired,
onShowApp: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired
store: PropTypes.object.isRequired
};

render () {
const { onClose, open, available } = this.props;
const { store } = this.props;

if (!store.modalOpen) {
return null;
}

return (
<Modal
compact
title='visible applications'
actions={ [
<Button label={ 'Done' } key='done' onClick={ onClose } icon={ <DoneIcon /> } />
<Button
label={ 'Done' }
key='done'
onClick={ store.closeModal }
icon={ <DoneIcon /> }
/>
] }
visible={ open }
visible
scroll>
<List>
{ available.map(this.renderApp) }
{ store.apps.map(this.renderApp) }
</List>
</Modal>
);
}

renderApp = (app) => {
const { hidden, onHideApp, onShowApp } = this.props;
const isHidden = hidden.includes(app.id);
const description = (
<div className={ styles.description }>
{ app.description }
</div>
);
const { store } = this.props;
const isHidden = store.hidden.includes(app.id);
const onCheck = () => {
if (isHidden) {
onShowApp(app.id);
store.showApp(app.id);
} else {
onHideApp(app.id);
store.hideApp(app.id);
}
};

return (
<ListItem
key={ app.id }
leftCheckbox={ <Checkbox checked={ !isHidden } onCheck={ onCheck } /> }
leftCheckbox={
<Checkbox
checked={ !isHidden }
onCheck={ onCheck }
/>
}
primaryText={ app.name }
secondaryText={ description } />
secondaryText={
<div className={ styles.description }>
{ app.description }
</div>
}
/>
);
}
}
19 changes: 13 additions & 6 deletions js/src/views/Dapps/Summary/summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ export default class Summary extends Component {
}

let image = <div className={ styles.image }>&nbsp;</div>;
if (app.image) {
image = <img src={ `http://127.0.0.1:${dappsPort}${app.image}` } className={ styles.image } />;
} else if (app.iconUrl) {
if (app.type === 'local') {
image = <img src={ `http://127.0.0.1:${dappsPort}/${app.id}/${app.iconUrl}` } className={ styles.image } />;
} else {
image = <img src={ `http://127.0.0.1:${dappsPort}${app.image}` } className={ styles.image } />;
}

return (
Expand All @@ -52,9 +52,16 @@ export default class Summary extends Component {
<div className={ styles.description }>
<ContainerTitle
className={ styles.title }
title={ <Link to={ `/app/${app.id}` }>{ app.name }</Link> }
byline={ app.description } />
<div className={ styles.author }>{ app.author }, v{ app.version }</div>
title={
<Link to={ `/app/${app.id}` }>
{ app.name }
</Link>
}
byline={ app.description }
/>
<div className={ styles.author }>
{ app.author }, v{ app.version }
</div>
{ this.props.children }
</div>
</Container>
Expand Down
119 changes: 12 additions & 107 deletions js/src/views/Dapps/dapps.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,71 +15,53 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react';

import Contracts from '../../contracts';
import { hashToImageUrl } from '../../redux/util';
import { Actionbar, Page } from '../../ui';
import FlatButton from 'material-ui/FlatButton';
import EyeIcon from 'material-ui/svg-icons/image/remove-red-eye';

import { fetchAvailable } from './registry';
import { readHiddenApps, writeHiddenApps } from './hidden';
import DappsStore from './dappsStore';

import AddDapps from './AddDapps';
import Summary from './Summary';

import styles from './dapps.css';

@observer
export default class Dapps extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
}

state = {
available: [],
hidden: [],
modalOpen: false
}

componentDidMount () {
this.loadAvailableApps();
}
store = new DappsStore(this.context.api);

render () {
const { available, hidden, modalOpen } = this.state;
const apps = available.filter((app) => !hidden.includes(app.id));

return (
<div>
<AddDapps
available={ available }
hidden={ hidden }
open={ modalOpen }
onHideApp={ this.onHideApp }
onShowApp={ this.onShowApp }
onClose={ this.closeModal }
/>
<AddDapps store={ this.store } />
<Actionbar
className={ styles.toolbar }
title='Decentralized Applications'
buttons={ [
<FlatButton label='edit' key='edit' icon={ <EyeIcon /> } onClick={ this.openModal } />
<FlatButton
label='edit'
key='edit'
icon={ <EyeIcon /> }
onClick={ this.store.openModal }
/>
] }
/>
<Page>
<div className={ styles.list }>
{ apps.map(this.renderApp) }
{ this.store.visible.map(this.renderApp) }
</div>
</Page>
</div>
);
}

renderApp = (app) => {
if (!app.name) {
return null;
}

return (
<div
className={ styles.item }
Expand All @@ -88,81 +70,4 @@ export default class Dapps extends Component {
</div>
);
}

onHideApp = (id) => {
const { hidden } = this.state;
const newHidden = hidden.concat(id);

this.setState({ hidden: newHidden });
writeHiddenApps(newHidden);
}

onShowApp = (id) => {
const { hidden } = this.state;
const newHidden = hidden.filter((_id) => _id !== id);

this.setState({ hidden: newHidden });
writeHiddenApps(newHidden);
}

openModal = () => {
this.setState({ modalOpen: true });
};

closeModal = () => {
this.setState({ modalOpen: false });
};

loadAvailableApps () {
const { api } = this.context;

fetchAvailable(api)
.then((available) => {
this.setState({
available,
hidden: readHiddenApps()
});

this.loadContent();
});
}

loadContent () {
const { api } = this.context;
const { available } = this.state;
const { dappReg } = Contracts.get();

return Promise
.all(available.map((app) => dappReg.getImage(app.id)))
.then((images) => {
const _available = images
.map(hashToImageUrl)
.map((image, index) => Object.assign({}, available[index], { image }));

this.setState({ available: _available });
const _networkApps = _available.filter((app) => app.network);

return Promise
.all(_networkApps.map((app) => dappReg.getContent(app.id)))
.then((content) => {
const networkApps = content.map((_contentHash, index) => {
const networkApp = _networkApps[index];
const contentHash = api.util.bytesToHex(_contentHash).substr(2);
const app = _available.find((_app) => _app.id === networkApp.id);

console.log(`found content for ${app.id} at ${contentHash}`);
return Object.assign({}, app, { contentHash });
});

this.setState({
available: _available.map((app) => {
return Object.assign({}, networkApps.find((napp) => app.id === napp.id) || app);
})
});
});
})
.catch((error) => {
console.warn('loadImages', error);
});
}
}
Loading

0 comments on commit 34998a7

Please sign in to comment.