add ui for removing contributors

This commit is contained in:
Jonathan Rainville 2019-04-10 15:14:58 -04:00
parent 21b2b6cb43
commit 5d069afb06
No known key found for this signature in database
GPG Key ID: 5F4630B759727D9C
4 changed files with 120 additions and 9 deletions

View File

@ -1,21 +1,38 @@
/*global web3*/
import React from 'react';
import {Button, Form, Alert} from 'react-bootstrap';
import React, {Fragment} from 'react';
import {Button, Form, Alert, ListGroup, OverlayTrigger, Tooltip, Modal} from 'react-bootstrap';
import ValidatedForm from 'react-validation/build/form';
import Input from 'react-validation/build/input';
import {required, isAddress} from '../validators';
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faTrash} from "@fortawesome/free-solid-svg-icons";
import {addContributor} from '../services/Meritocracy';
import {addContributor, getFormattedContributorList} from '../services/Meritocracy';
import './admin.scss';
class Admin extends React.Component {
state = {
contributorName: '',
contributorAddress: '',
busy: false,
busy: true,
error: '',
successMsg: ''
successMsg: '',
contributorList: [],
showDeleteModal: false,
focusedContributorIndex: -1
};
async componentDidMount() {
try {
const contributorList = await getFormattedContributorList();
this.setState({busy: false, contributorList});
} catch (e) {
this.setState({errorMsg: e.message || e});
}
}
onChange = (name, e) => {
this.setState({[name]: e.target.value});
};
@ -31,10 +48,24 @@ class Admin extends React.Component {
}
};
render() {
const {contributorAddress, contributorName, error, busy} = this.state;
removeContributor = (e, contributorIndex) => {
e.preventDefault();
this.setState({focusedContributorIndex: contributorIndex, showDeleteModal: true});
};
return (<div>
doRemove = () => {
this.setState({focusedContributorIndex: -1, showDeleteModal: false});
};
handleClose = () => {
this.setState({showDeleteModal: false});
};
render() {
const {contributorAddress, contributorName, error, busy, contributorList, successMsg, focusedContributorIndex} = this.state;
const currentContributor = focusedContributorIndex > -1 ? contributorList[focusedContributorIndex] : {};
return (<Fragment>
<h2>Admin Panel</h2>
{error && <Alert variant="danger">{error}</Alert>}
{successMsg && <Alert variant="success">{successMsg}</Alert>}
@ -58,7 +89,44 @@ class Admin extends React.Component {
</Form.Group>
<Button variant="primary" onClick={(e) => this.addContributor(e)}>Add</Button>
</ValidatedForm>
</div>);
<h3>Contributor List</h3>
<ListGroup>
{contributorList.map((contributor, idx) => (
<ListGroup.Item key={contributor.value} action>
{contributor.label}: {contributor.value}
<div className="contributor-controls float-right">
<OverlayTrigger placement="top"
overlay={
<Tooltip>
Delete contributor
</Tooltip>
}>
<FontAwesomeIcon icon={faTrash} className="text-danger icon" onClick={(e) => this.removeContributor(e, idx)}/>
</OverlayTrigger>
</div>
</ListGroup.Item>
))}
</ListGroup>
<Modal show={this.state.showDeleteModal} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Are you sure you want to remove this contributor?</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Name: {currentContributor.label}</p>
<p>Address: {currentContributor.value}</p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.handleClose}>
Cancel
</Button>
<Button variant="danger" onClick={this.doRemove}>
Remove
</Button>
</Modal.Footer>
</Modal>
</Fragment>);
}
}

View File

@ -0,0 +1,5 @@
.contributor-controls {
.icon {
cursor: pointer;
}
}

35
package-lock.json generated
View File

@ -93,6 +93,36 @@
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz",
"integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw=="
},
"@fortawesome/fontawesome-common-types": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.17.tgz",
"integrity": "sha512-DEYsEb/iiGVoMPQGjhG2uOylLVuMzTxOxysClkabZ5n80Q3oFDWGnshCLKvOvKoeClsgmKhWVrnnqvsMI1cAbw=="
},
"@fortawesome/fontawesome-svg-core": {
"version": "1.2.17",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.17.tgz",
"integrity": "sha512-TORMW/wIX2QyyGBd4XwHGPir4/0U18Wxf+iDBAUW3EIJ0/VC/ZMpJOiyiCe1f8g9h0PPzA7sqVtl8JtTUtm4uA==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.17"
}
},
"@fortawesome/free-solid-svg-icons": {
"version": "5.8.1",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.8.1.tgz",
"integrity": "sha512-FUcxR75PtMOo3ihRHJOZz64IsWIVdWgB2vCMLJjquTv487wVVCMH5H5gWa72et2oI9lKKD2jvjQ+y+7mxhscVQ==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.17"
}
},
"@fortawesome/react-fontawesome": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.4.tgz",
"integrity": "sha512-GwmxQ+TK7PEdfSwvxtGnMCqrfEm0/HbRHArbUudsYiy9KzVCwndxa2KMcfyTQ8El0vROrq8gOOff09RF1oQe8g==",
"requires": {
"humps": "^2.0.1",
"prop-types": "^15.5.10"
}
},
"@react-bootstrap/react-popper": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@react-bootstrap/react-popper/-/react-popper-1.2.1.tgz",
@ -431,6 +461,11 @@
"react-is": "^16.7.0"
}
},
"humps": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz",
"integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao="
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",

View File

@ -10,6 +10,9 @@
"license": "ISC",
"homepage": "",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.17",
"@fortawesome/free-solid-svg-icons": "^5.8.1",
"@fortawesome/react-fontawesome": "^0.1.4",
"bootstrap": "^4.3.1",
"embark-solc": "^4.0.1",
"embarkjs-connector-web3": "^4.0.0",