Refactoring of the Dapp Registry (#4589)
* Add React Hot Loader to DappReg dapp * Updated colours * Add DappCards * Dapp Modal with manifest displayed * Add input to the Dapp Modal * WIP // Editing a Dapp * Clean-Up * Linting * CleanUp and separate dapp from dappS * Semi-working updates * Working Editing of a Dapp * OCD * Linting * Add a Dapp -- WIP * Register a new Dapp * WIP Dapps * Working update / delete / register * Better promises * Working updates for DappReg * Fully functional again ! * Generic Card Component * Dashed Register Card * Cleanups * Cleanups * Add Actions to Modal * Clean-Up * Better Close Icon * Single place for Registry version // Fetch meta-data from Registry * Fixing test * Fix saving changes in dapp reg * PR Grumbles - Part I * PR Grumble - Part I * PR Grumble - Part II * DappReg Contract owner can delete dapps
This commit is contained in:
committed by
Jaco Greeff
parent
e15f60b819
commit
eebb8b87a4
@@ -15,95 +15,120 @@
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@import '../_colors.css';
|
||||
@import '../_utils.css';
|
||||
|
||||
.modal {
|
||||
.body {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
z-index: 50;
|
||||
align-items: center;
|
||||
background-color: $modal-bg;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 150;
|
||||
|
||||
&.secondary {
|
||||
align-items: flex-start;
|
||||
z-index: 200;
|
||||
|
||||
.content {
|
||||
line-height: 1.5rem;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
background: #fff;
|
||||
border-radius: 0 0 0.25em 0.25em;
|
||||
margin: 0 auto;
|
||||
max-width: 840px;
|
||||
text-align: left;
|
||||
width: 85vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
line-height: 1.5em;
|
||||
padding: 2em;
|
||||
text-align: center;
|
||||
.close {
|
||||
composes: bezier-transform;
|
||||
|
||||
.section {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-size: 4rem;
|
||||
opacity: 0.75;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
right: 1rem;
|
||||
top: 0.25rem;
|
||||
|
||||
&.error {
|
||||
color: #f44;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
|
||||
.section+.section {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
.closeIcon {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 0.5em 1.625em;
|
||||
text-align: right;
|
||||
}
|
||||
.closeIcon {
|
||||
composes: bezier-transform;
|
||||
|
||||
.header {
|
||||
background: #44e;
|
||||
color: #fff;
|
||||
opacity: 0.85;
|
||||
padding: 1em;
|
||||
height: 3rem;
|
||||
width: 3rem;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&.error {
|
||||
background: #e44;
|
||||
}
|
||||
}
|
||||
.dialog {
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
max-width: 740px;
|
||||
width: 75vw;
|
||||
|
||||
> * {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
|
||||
.section {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
* {
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
background: rgba(204, 204, 204, 0.7);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 49;
|
||||
.section + .section {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.account {
|
||||
div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.footer {
|
||||
padding: 0.5em 1.625em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.hint {
|
||||
display: block !important;
|
||||
color: #888;
|
||||
font-size: 0.75em;
|
||||
margin-top: -0.5em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header {
|
||||
background-color: $blue;
|
||||
color: white;
|
||||
min-height: 3rem;
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
&,
|
||||
& > * {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
|
||||
@@ -14,53 +14,147 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import keycode from 'keycode';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Button from '../Button';
|
||||
|
||||
import styles from './modal.css';
|
||||
import CloseImage from '~/../assets/images/dapps/close.svg';
|
||||
|
||||
export default class Modal extends Component {
|
||||
static propTypes = {
|
||||
buttons: PropTypes.node,
|
||||
actions: PropTypes.array,
|
||||
children: PropTypes.node,
|
||||
error: PropTypes.object,
|
||||
header: PropTypes.string
|
||||
}
|
||||
header: PropTypes.node,
|
||||
secondary: PropTypes.bool,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onConfirm: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
actions: null,
|
||||
secondary: false
|
||||
};
|
||||
|
||||
render () {
|
||||
const { children, buttons, error, header } = this.props;
|
||||
const { children, actions, header, secondary } = this.props;
|
||||
|
||||
const modalClasses = [ styles.modal ];
|
||||
|
||||
if (secondary) {
|
||||
modalClasses.push(styles.secondary);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.modal }>
|
||||
<div className={ styles.overlay } />
|
||||
<div className={ styles.body }>
|
||||
<div className={ styles.dialog }>
|
||||
<div className={ `${styles.header} ${error ? styles.error : ''}` }>
|
||||
{ header }
|
||||
</div>
|
||||
<div className={ styles.content }>
|
||||
{ error ? this.renderError() : children }
|
||||
</div>
|
||||
<div className={ styles.footer }>
|
||||
{ buttons }
|
||||
<div
|
||||
className={ modalClasses.join(' ') }
|
||||
onClick={ this.handleClose }
|
||||
onKeyUp={ this.handleKeyPress }
|
||||
>
|
||||
<div
|
||||
className={ styles.dialog }
|
||||
onClick={ this.stopEvent }
|
||||
ref={ this.handleSetRef }
|
||||
tabIndex={ open ? 0 : null }
|
||||
>
|
||||
<div className={ styles.header }>
|
||||
{ header }
|
||||
<div
|
||||
className={ styles.close }
|
||||
onClick={ this.handleClose }
|
||||
onKeyPress={ this.handleCloseKeyPress }
|
||||
tabIndex={ open ? 0 : null }
|
||||
title='close'
|
||||
>
|
||||
<img
|
||||
className={ styles.closeIcon }
|
||||
src={ CloseImage }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={ styles.content }>
|
||||
{ children }
|
||||
</div>
|
||||
|
||||
{ actions ? this.renderActions(actions) : null }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderError () {
|
||||
const { error } = this.props;
|
||||
|
||||
renderActions (actions) {
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.section }>
|
||||
Your operation failed to complete sucessfully. The following error was returned:
|
||||
</div>
|
||||
<div className={ `${styles.section} ${styles.error}` }>
|
||||
{ error.toString() }
|
||||
</div>
|
||||
<div className={ styles.footer }>
|
||||
{ actions.map((action) => {
|
||||
let onClick = () => {};
|
||||
|
||||
switch (action.type) {
|
||||
case 'confirm':
|
||||
onClick = this.handleConfirm;
|
||||
break;
|
||||
|
||||
case 'close':
|
||||
onClick = this.handleClose;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={ action.type }
|
||||
label={ action.label }
|
||||
warning={ action.warning }
|
||||
onClick={ onClick }
|
||||
/>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
stopEvent = (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handleKeyPress = (event) => {
|
||||
const codeName = keycode(event);
|
||||
|
||||
if (codeName === 'esc') {
|
||||
return this.handleClose();
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
handleCloseKeyPress = (event) => {
|
||||
const codeName = keycode(event);
|
||||
|
||||
if (codeName === 'enter') {
|
||||
return this.handleClose();
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
handleSetRef = (containerRef) => {
|
||||
// Focus after the modal is open
|
||||
setTimeout(() => {
|
||||
const element = ReactDOM.findDOMNode(containerRef);
|
||||
|
||||
element && element.focus();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
handleConfirm = () => {
|
||||
this.props.onConfirm && this.props.onConfirm();
|
||||
}
|
||||
|
||||
handleClose = () => {
|
||||
this.props.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user