Available Dapp selection alignment with Permissions (Portal) (#4374)
* Manage default accounts * Portal * Portal * Allow Portal to be used in as both top-level and popover * modal/popover variable naming * Move to Portal * export Portal in ~/ui * WIP * Tags handle empty values * Export AccountCard in ~/ui * Allow ETH-only & zero display * Use ui/Balance for balance display * Add tests for Balance & Tags component availability * WIP * Default overlay display to block (not flex) * Revert block * WIP * Add className, optional handlers only * WIP * Properly handle optional onKeyDown * Selection updated * Align margins * Remove old code * Remove debug logging * TransitionGroup for animations * No anim * Cleanups * Revert addons removal * Fix tests * WIP * Add onClick to Container * Create ui/DappCard component * WIP * Pass dummy displayApps * Rename DappsVisible back to AddDapps (easier git diff) * Rename CSS * Fix tests after merge
This commit is contained in:
parent
1547af191b
commit
535ebb1f2f
@ -15,15 +15,24 @@
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.modal {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-top: 1.5em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: .5em !important;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 1.5em;
|
||||
|
||||
.background {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
margin: 0 -1.5em;
|
||||
padding: 0.5em 1.5em;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -37,3 +46,26 @@
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
.selectIcon {
|
||||
position: absolute;
|
||||
right: 0.5em;
|
||||
top: 0.5em;
|
||||
}
|
||||
|
||||
.selected,
|
||||
.unselected {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.unselected {
|
||||
background: rgba(0, 0, 0, 0.4) !important;
|
||||
|
||||
.selectIcon {
|
||||
opacity: 0.15;
|
||||
}
|
||||
}
|
||||
|
||||
.selected {
|
||||
background: rgba(255, 255, 255, 0.15) !important;
|
||||
}
|
||||
|
@ -14,14 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Checkbox } from 'material-ui';
|
||||
import { List, ListItem } from 'material-ui/List';
|
||||
import { observer } from 'mobx-react';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Modal, Button } from '~/ui';
|
||||
import { DoneIcon } from '~/ui/Icons';
|
||||
import { ContainerTitle, DappCard, Portal, SectionList } from '~/ui';
|
||||
import { CheckIcon } from '~/ui/Icons';
|
||||
|
||||
import styles from './addDapps.css';
|
||||
|
||||
@ -39,32 +37,23 @@ export default class AddDapps extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
actions={ [
|
||||
<Button
|
||||
icon={ <DoneIcon /> }
|
||||
key='done'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='dapps.add.button.done'
|
||||
defaultMessage='Done'
|
||||
/>
|
||||
}
|
||||
onClick={ store.closeModal }
|
||||
/>
|
||||
] }
|
||||
compact
|
||||
<Portal
|
||||
className={ styles.modal }
|
||||
onClose={ store.closeModal }
|
||||
open
|
||||
>
|
||||
<ContainerTitle
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='dapps.add.label'
|
||||
defaultMessage='visible applications'
|
||||
/>
|
||||
}
|
||||
visible
|
||||
>
|
||||
/>
|
||||
<div className={ styles.container }>
|
||||
<div className={ styles.warning } />
|
||||
{
|
||||
this.renderList(store.sortedLocal,
|
||||
this.renderList(store.sortedLocal, store.displayApps,
|
||||
<FormattedMessage
|
||||
id='dapps.add.local.label'
|
||||
defaultMessage='Applications locally available'
|
||||
@ -76,7 +65,7 @@ export default class AddDapps extends Component {
|
||||
)
|
||||
}
|
||||
{
|
||||
this.renderList(store.sortedBuiltin,
|
||||
this.renderList(store.sortedBuiltin, store.displayApps,
|
||||
<FormattedMessage
|
||||
id='dapps.add.builtin.label'
|
||||
defaultMessage='Applications bundled with Parity'
|
||||
@ -88,7 +77,7 @@ export default class AddDapps extends Component {
|
||||
)
|
||||
}
|
||||
{
|
||||
this.renderList(store.sortedNetwork,
|
||||
this.renderList(store.sortedNetwork, store.displayApps,
|
||||
<FormattedMessage
|
||||
id='dapps.add.network.label'
|
||||
defaultMessage='Applications on the global network'
|
||||
@ -99,11 +88,12 @@ export default class AddDapps extends Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
</Portal>
|
||||
);
|
||||
}
|
||||
|
||||
renderList (items, header, byline) {
|
||||
renderList (items, visibleItems, header, byline) {
|
||||
if (!items || !items.length) {
|
||||
return null;
|
||||
}
|
||||
@ -114,41 +104,40 @@ export default class AddDapps extends Component {
|
||||
<div className={ styles.header }>{ header }</div>
|
||||
<div className={ styles.byline }>{ byline }</div>
|
||||
</div>
|
||||
<List>
|
||||
{ items.map(this.renderApp) }
|
||||
</List>
|
||||
<SectionList
|
||||
items={ items }
|
||||
noStretch
|
||||
renderItem={ this.renderApp }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderApp = (app) => {
|
||||
const { store } = this.props;
|
||||
const isHidden = !store.displayApps[app.id].visible;
|
||||
const isVisible = store.displayApps[app.id].visible;
|
||||
|
||||
const onCheck = () => {
|
||||
if (isHidden) {
|
||||
store.showApp(app.id);
|
||||
} else {
|
||||
const onClick = () => {
|
||||
if (isVisible) {
|
||||
store.hideApp(app.id);
|
||||
} else {
|
||||
store.showApp(app.id);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
<DappCard
|
||||
app={ app }
|
||||
className={
|
||||
isVisible
|
||||
? styles.selected
|
||||
: styles.unselected
|
||||
}
|
||||
key={ app.id }
|
||||
leftCheckbox={
|
||||
<Checkbox
|
||||
checked={ !isHidden }
|
||||
onCheck={ onCheck }
|
||||
/>
|
||||
}
|
||||
primaryText={ app.name }
|
||||
secondaryText={
|
||||
<div className={ styles.description }>
|
||||
{ app.description }
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
onClick={ onClick }
|
||||
>
|
||||
<CheckIcon className={ styles.selectIcon } />
|
||||
</DappCard>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -33,13 +33,13 @@ describe('modals/AddDapps', () => {
|
||||
|
||||
it('does not render the modal with modalOpen = false', () => {
|
||||
expect(
|
||||
renderShallow({ modalOpen: false }).find('Connect(Modal)')
|
||||
renderShallow({ modalOpen: false }).find('Portal')
|
||||
).to.have.length(0);
|
||||
});
|
||||
|
||||
it('does render the modal with modalOpen = true', () => {
|
||||
expect(
|
||||
renderShallow({ modalOpen: true }).find('Connect(Modal)')
|
||||
renderShallow({ modalOpen: true }).find('Portal')
|
||||
).to.have.length(1);
|
||||
});
|
||||
});
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
import AddAddress from './AddAddress';
|
||||
import AddContract from './AddContract';
|
||||
import AddDapps from './AddDapps';
|
||||
import CreateAccount from './CreateAccount';
|
||||
import CreateWallet from './CreateWallet';
|
||||
import DappPermissions from './DappPermissions';
|
||||
import DappsVisible from './AddDapps';
|
||||
import DeleteAccount from './DeleteAccount';
|
||||
import DeployContract from './DeployContract';
|
||||
import EditMeta from './EditMeta';
|
||||
@ -37,10 +37,10 @@ import WalletSettings from './WalletSettings';
|
||||
export {
|
||||
AddAddress,
|
||||
AddContract,
|
||||
AddDapps,
|
||||
CreateAccount,
|
||||
CreateWallet,
|
||||
DappPermissions,
|
||||
DappsVisible,
|
||||
DeleteAccount,
|
||||
DeployContract,
|
||||
EditMeta,
|
||||
|
@ -29,15 +29,14 @@ export default class Container extends Component {
|
||||
className: PropTypes.string,
|
||||
compact: PropTypes.bool,
|
||||
light: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
style: PropTypes.object,
|
||||
tabIndex: PropTypes.number,
|
||||
title: nodeOrStringProptype()
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, className, compact, light, style, tabIndex } = this.props;
|
||||
const classes = `${styles.container} ${light ? styles.light : ''} ${className}`;
|
||||
|
||||
const { children, className, compact, light, onClick, style, tabIndex } = this.props;
|
||||
const props = {};
|
||||
|
||||
if (Number.isInteger(tabIndex)) {
|
||||
@ -45,8 +44,27 @@ export default class Container extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ classes } style={ style } { ...props }>
|
||||
<Card className={ compact ? styles.compact : styles.padded }>
|
||||
<div
|
||||
className={
|
||||
[
|
||||
styles.container,
|
||||
light
|
||||
? styles.light
|
||||
: '',
|
||||
className
|
||||
].join(' ')
|
||||
}
|
||||
style={ style }
|
||||
{ ...props }
|
||||
>
|
||||
<Card
|
||||
className={
|
||||
compact
|
||||
? styles.compact
|
||||
: styles.padded
|
||||
}
|
||||
onClick={ onClick }
|
||||
>
|
||||
{ this.renderTitle() }
|
||||
{ children }
|
||||
</Card>
|
||||
|
@ -17,59 +17,80 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import { Container, ContainerTitle, DappIcon, Tags } from '~/ui';
|
||||
import Container, { Title as ContainerTitle } from '~/ui/Container';
|
||||
import DappIcon from '~/ui/DappIcon';
|
||||
import Tags from '~/ui/Tags';
|
||||
|
||||
import styles from './summary.css';
|
||||
import styles from './dappCard.css';
|
||||
|
||||
export default class Summary extends Component {
|
||||
export default class DappCard extends Component {
|
||||
static propTypes = {
|
||||
app: PropTypes.object.isRequired,
|
||||
children: PropTypes.node
|
||||
}
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
showLink: PropTypes.bool,
|
||||
showTags: PropTypes.bool
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
showLink: false,
|
||||
showTags: false
|
||||
};
|
||||
|
||||
render () {
|
||||
const { app } = this.props;
|
||||
const { app, children, className, onClick, showLink, showTags } = this.props;
|
||||
|
||||
if (!app) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const link = this.renderLink(app);
|
||||
|
||||
return (
|
||||
<Container className={ styles.container }>
|
||||
<Container
|
||||
className={
|
||||
[styles.container, className].join(' ')
|
||||
}
|
||||
onClick={ onClick }
|
||||
>
|
||||
<DappIcon
|
||||
app={ app }
|
||||
className={ styles.image }
|
||||
/>
|
||||
<Tags tags={ [app.type] } />
|
||||
<Tags
|
||||
tags={
|
||||
showTags
|
||||
? [app.type]
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<div className={ styles.description }>
|
||||
<ContainerTitle
|
||||
className={ styles.title }
|
||||
title={ link }
|
||||
title={
|
||||
showLink
|
||||
? this.renderLink(app)
|
||||
: app.name
|
||||
}
|
||||
byline={ app.description }
|
||||
/>
|
||||
<div className={ styles.author }>
|
||||
{ app.author }, v{ app.version }
|
||||
</div>
|
||||
{ this.props.children }
|
||||
{ children }
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
renderLink (app) {
|
||||
// Special case for web dapp
|
||||
if (app.url === 'web') {
|
||||
return (
|
||||
<Link to={ `/web` }>
|
||||
{ app.name }
|
||||
</Link>
|
||||
);
|
||||
<Link
|
||||
to={
|
||||
app.url === 'web'
|
||||
? '/web'
|
||||
: `/app/${app.id}`
|
||||
}
|
||||
|
||||
return (
|
||||
<Link to={ `/app/${app.id}` }>
|
||||
>
|
||||
{ app.name }
|
||||
</Link>
|
||||
);
|
@ -14,4 +14,4 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default from './summary';
|
||||
export default from './dappCard';
|
@ -30,6 +30,7 @@ import Container, { Title as ContainerTitle } from './Container';
|
||||
import ContextProvider from './ContextProvider';
|
||||
import CopyToClipboard from './CopyToClipboard';
|
||||
import CurrencySymbol from './CurrencySymbol';
|
||||
import DappCard from './DappCard';
|
||||
import DappIcon from './DappIcon';
|
||||
import Editor from './Editor';
|
||||
import Errors from './Errors';
|
||||
@ -79,6 +80,7 @@ export {
|
||||
CopyToClipboard,
|
||||
CurrencySymbol,
|
||||
DappIcon,
|
||||
DappCard,
|
||||
Editor,
|
||||
Errors,
|
||||
FEATURES,
|
||||
|
@ -21,14 +21,13 @@ import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { AddDapps, DappPermissions } from '~/modals';
|
||||
import { DappPermissions, DappsVisible } from '~/modals';
|
||||
import PermissionStore from '~/modals/DappPermissions/store';
|
||||
import { Actionbar, Button, Page } from '~/ui';
|
||||
import { Actionbar, Button, DappCard, Page } from '~/ui';
|
||||
import { LockedIcon, VisibleIcon } from '~/ui/Icons';
|
||||
|
||||
import UrlButton from './UrlButton';
|
||||
import DappsStore from './dappsStore';
|
||||
import Summary from './Summary';
|
||||
|
||||
import styles from './dapps.css';
|
||||
|
||||
@ -82,8 +81,8 @@ class Dapps extends Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AddDapps store={ this.store } />
|
||||
<DappPermissions store={ this.permissionStore } />
|
||||
<DappsVisible store={ this.store } />
|
||||
<Actionbar
|
||||
className={ styles.toolbar }
|
||||
title={
|
||||
@ -146,7 +145,11 @@ class Dapps extends Component {
|
||||
className={ styles.item }
|
||||
key={ app.id }
|
||||
>
|
||||
<Summary app={ app } />
|
||||
<DappCard
|
||||
app={ app }
|
||||
showLink
|
||||
showTags
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user