feat: arbitration approval UI (#358)
* feat: arbitration approval UI * feat: display number of pending requests (#359)
This commit is contained in:
parent
8808fb7f56
commit
44650d0adb
|
@ -1,4 +1,4 @@
|
|||
import {ARBITRATION_UNSOLVED, GET_DISPUTED_ESCROWS, RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, BUY_LICENSE,CANCEL_ARBITRATOR_SELECTION_ACTIONS, CHECK_LICENSE_OWNER, LOAD_PRICE, LOAD_ARBITRATION, GET_ARBITRATORS, OPEN_DISPUTE, CANCEL_DISPUTE, REQUEST_ARBITRATOR, CANCEL_ARBITRATOR_REQUEST, CHANGE_ACCEPT_EVERYONE} from './constants';
|
||||
import {ARBITRATION_UNSOLVED, GET_DISPUTED_ESCROWS, RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, BUY_LICENSE,CANCEL_ARBITRATOR_SELECTION_ACTIONS, CHECK_LICENSE_OWNER, LOAD_PRICE, LOAD_ARBITRATION, GET_ARBITRATORS, OPEN_DISPUTE, CANCEL_DISPUTE, REQUEST_ARBITRATOR, CANCEL_ARBITRATOR_REQUEST, CHANGE_ACCEPT_EVERYONE, GET_ARBITRATION_REQUESTS, ACCEPT_ARBITRATOR_REQUEST, REJECT_ARBITRATOR_REQUEST} from './constants';
|
||||
import Escrow from '../../../embarkArtifacts/contracts/Escrow';
|
||||
import ArbitrationLicense from '../../../embarkArtifacts/contracts/ArbitrationLicense';
|
||||
import OwnedUpgradeabilityProxy from '../../../embarkArtifacts/contracts/OwnedUpgradeabilityProxy';
|
||||
|
@ -44,3 +44,9 @@ export const cancelArbitratorRequest = (arbitrator) => ({type: CANCEL_ARBITRATOR
|
|||
export const cancelArbitratorActions = () => ({type: CANCEL_ARBITRATOR_SELECTION_ACTIONS});
|
||||
|
||||
export const changeAcceptEveryone = (acceptAny) => ({type: CHANGE_ACCEPT_EVERYONE, acceptAny, toSend: ArbitrationLicense.methods.changeAcceptAny(acceptAny)});
|
||||
|
||||
export const getArbitratorRequests = (arbitrator) => ({type: GET_ARBITRATION_REQUESTS, arbitrator});
|
||||
|
||||
export const acceptRequest = (id) => ({type: ACCEPT_ARBITRATOR_REQUEST, id, toSend: ArbitrationLicense.methods.acceptRequest(id)});
|
||||
|
||||
export const rejectRequest = (id) => ({type: REJECT_ARBITRATOR_REQUEST, id, toSend: ArbitrationLicense.methods.rejectRequest(id)});
|
||||
|
|
|
@ -60,9 +60,22 @@ export const CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS = 'CHANGE_ACCEPT_EVERYONE_PRE_SU
|
|||
export const CHANGE_ACCEPT_EVERYONE_SUCCEEDED = 'CHANGE_ACCEPT_EVERYONE_SUCCEEDED';
|
||||
export const CHANGE_ACCEPT_EVERYONE_FAILED = 'CHANGE_ACCEPT_EVERYONE_FAILED';
|
||||
|
||||
export const GET_ARBITRATION_REQUESTS = 'GET_ARBITRATION_REQUESTS';
|
||||
export const GET_ARBITRATION_REQUESTS_SUCCEEDED = 'GET_ARBITRATION_REQUESTS_SUCCEEDED';
|
||||
export const GET_ARBITRATION_REQUESTS_FAILED = 'GET_ARBITRATION_REQUESTS_FAILED';
|
||||
|
||||
export const NONE = '0';
|
||||
export const AWAIT = '1';
|
||||
export const ACCEPTED = '2';
|
||||
export const REJECTED = '3';
|
||||
export const CLOSED = '4';
|
||||
|
||||
export const ACCEPT_ARBITRATOR_REQUEST = 'ACCEPT_ARBITRATOR_REQUEST';
|
||||
export const ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS = 'ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS';
|
||||
export const ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED = 'ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED';
|
||||
export const ACCEPT_ARBITRATOR_REQUEST_FAILED = 'ACCEPT_ARBITRATOR_REQUEST_FAILED';
|
||||
|
||||
export const REJECT_ARBITRATOR_REQUEST = 'REJECT_ARBITRATOR_REQUEST';
|
||||
export const REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS = 'REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS';
|
||||
export const REJECT_ARBITRATOR_REQUEST_SUCCEEDED = 'REJECT_ARBITRATOR_REQUEST_SUCCEEDED';
|
||||
export const REJECT_ARBITRATOR_REQUEST_FAILED = 'REJECT_ARBITRATOR_REQUEST_FAILED';
|
||||
|
|
|
@ -41,7 +41,19 @@ import {
|
|||
CHANGE_ACCEPT_EVERYONE,
|
||||
CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS,
|
||||
CHANGE_ACCEPT_EVERYONE_FAILED,
|
||||
CHANGE_ACCEPT_EVERYONE_SUCCEEDED
|
||||
CHANGE_ACCEPT_EVERYONE_SUCCEEDED,
|
||||
GET_ARBITRATION_REQUESTS_SUCCEEDED,
|
||||
GET_ARBITRATION_REQUESTS_FAILED,
|
||||
ACCEPT_ARBITRATOR_REQUEST,
|
||||
ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS,
|
||||
ACCEPT_ARBITRATOR_REQUEST_FAILED,
|
||||
ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED,
|
||||
REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS,
|
||||
REJECT_ARBITRATOR_REQUEST_FAILED,
|
||||
REJECT_ARBITRATOR_REQUEST,
|
||||
REJECT_ARBITRATOR_REQUEST_SUCCEEDED,
|
||||
REJECTED,
|
||||
ACCEPTED
|
||||
} from './constants';
|
||||
import { fromTokenDecimals } from '../../utils/numbers';
|
||||
import {RESET_STATE, PURGE_STATE} from "../network/constants";
|
||||
|
@ -52,7 +64,8 @@ const DEFAULT_STATE = {
|
|||
receipt: null,
|
||||
price: Number.MAX_SAFE_INTEGER,
|
||||
loading: false,
|
||||
error: ''
|
||||
error: '',
|
||||
arbitratorRequests: []
|
||||
};
|
||||
|
||||
function reducer(state = DEFAULT_STATE, action) {
|
||||
|
@ -70,6 +83,8 @@ function reducer(state = DEFAULT_STATE, action) {
|
|||
case REQUEST_ARBITRATOR_PRE_SUCCESS:
|
||||
case CANCEL_ARBITRATOR_REQUEST_PRE_SUCCESS:
|
||||
case CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS:
|
||||
case ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS:
|
||||
case REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS:
|
||||
return {
|
||||
...state, ...{
|
||||
txHash: action.txHash
|
||||
|
@ -112,6 +127,9 @@ function reducer(state = DEFAULT_STATE, action) {
|
|||
case REQUEST_ARBITRATOR_FAILED:
|
||||
case CANCEL_ARBITRATOR_REQUEST_FAILED:
|
||||
case CHANGE_ACCEPT_EVERYONE_FAILED:
|
||||
case GET_ARBITRATION_REQUESTS_FAILED:
|
||||
case ACCEPT_ARBITRATOR_REQUEST_FAILED:
|
||||
case REJECT_ARBITRATOR_REQUEST_FAILED:
|
||||
return {
|
||||
...state, ...{
|
||||
errorGet: action.error,
|
||||
|
@ -123,6 +141,8 @@ function reducer(state = DEFAULT_STATE, action) {
|
|||
case OPEN_DISPUTE:
|
||||
case RESOLVE_DISPUTE:
|
||||
case CHANGE_ACCEPT_EVERYONE:
|
||||
case ACCEPT_ARBITRATOR_REQUEST:
|
||||
case REJECT_ARBITRATOR_REQUEST:
|
||||
return {
|
||||
...state, ...{
|
||||
loading: true
|
||||
|
@ -231,6 +251,33 @@ function reducer(state = DEFAULT_STATE, action) {
|
|||
error: action.error,
|
||||
loading: false
|
||||
};
|
||||
case GET_ARBITRATION_REQUESTS_SUCCEEDED:
|
||||
return {
|
||||
...state,
|
||||
arbitratorRequests: action.requests
|
||||
};
|
||||
case REJECT_ARBITRATOR_REQUEST_SUCCEEDED:
|
||||
{
|
||||
const arbitratorRequests = [...state.arbitratorRequests];
|
||||
arbitratorRequests.find(x => x.id === action.id).status = REJECTED;
|
||||
return {
|
||||
...state,
|
||||
arbitratorRequests,
|
||||
loading: false
|
||||
};
|
||||
|
||||
}
|
||||
case ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED:
|
||||
{
|
||||
const arbitratorRequests = [...state.arbitratorRequests];
|
||||
arbitratorRequests.find(x => x.id === action.id).status = ACCEPTED;
|
||||
return {
|
||||
...state,
|
||||
arbitratorRequests,
|
||||
loading: false
|
||||
};
|
||||
|
||||
}
|
||||
case RESET_STATE: {
|
||||
return Object.assign({}, state, {
|
||||
arbitration: null,
|
||||
|
|
|
@ -6,14 +6,15 @@ import MetadataStore from '../../../embarkArtifacts/contracts/MetadataStore';
|
|||
import moment from 'moment';
|
||||
import {promiseEventEmitter, doTransaction} from '../../utils/saga';
|
||||
import {eventChannel} from "redux-saga";
|
||||
import {fork, takeEvery, call, put, take} from 'redux-saga/effects';
|
||||
import {fork, takeEvery, call, put, take, all} from 'redux-saga/effects';
|
||||
import {
|
||||
CLOSED, NONE,
|
||||
GET_DISPUTED_ESCROWS, GET_DISPUTED_ESCROWS_FAILED, GET_DISPUTED_ESCROWS_SUCCEEDED,
|
||||
RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, RESOLVE_DISPUTE_SUCCEEDED,
|
||||
RESOLVE_DISPUTE_PRE_SUCCESS, LOAD_ARBITRATION, LOAD_ARBITRATION_FAILED, LOAD_ARBITRATION_SUCCEEDED, GET_ARBITRATORS,
|
||||
GET_ARBITRATORS_SUCCEEDED, GET_ARBITRATORS_FAILED, BUY_LICENSE, BUY_LICENSE_FAILED, BUY_LICENSE_PRE_SUCCESS, BUY_LICENSE_SUCCEEDED,
|
||||
LOAD_PRICE, LOAD_PRICE_FAILED, LOAD_PRICE_SUCCEEDED, CHECK_LICENSE_OWNER, CHECK_LICENSE_OWNER_FAILED, CHECK_LICENSE_OWNER_SUCCEEDED,
|
||||
OPEN_DISPUTE, OPEN_DISPUTE_SUCCEEDED, OPEN_DISPUTE_FAILED, OPEN_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE, CANCEL_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE_SUCCEEDED, CANCEL_DISPUTE_FAILED, REQUEST_ARBITRATOR, REQUEST_ARBITRATOR_PRE_SUCCESS, REQUEST_ARBITRATOR_SUCCEEDED, REQUEST_ARBITRATOR_FAILED, CANCEL_ARBITRATOR_REQUEST, CANCEL_ARBITRATOR_REQUEST_SUCCEEDED, CANCEL_ARBITRATOR_REQUEST_FAILED, CANCEL_ARBITRATOR_REQUEST_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE, CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE_FAILED, CHANGE_ACCEPT_EVERYONE_SUCCEEDED
|
||||
OPEN_DISPUTE, OPEN_DISPUTE_SUCCEEDED, OPEN_DISPUTE_FAILED, OPEN_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE, CANCEL_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE_SUCCEEDED, CANCEL_DISPUTE_FAILED, REQUEST_ARBITRATOR, REQUEST_ARBITRATOR_PRE_SUCCESS, REQUEST_ARBITRATOR_SUCCEEDED, REQUEST_ARBITRATOR_FAILED, CANCEL_ARBITRATOR_REQUEST, CANCEL_ARBITRATOR_REQUEST_SUCCEEDED, CANCEL_ARBITRATOR_REQUEST_FAILED, CANCEL_ARBITRATOR_REQUEST_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE, CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE_FAILED, CHANGE_ACCEPT_EVERYONE_SUCCEEDED, GET_ARBITRATION_REQUESTS, GET_ARBITRATION_REQUESTS_FAILED, GET_ARBITRATION_REQUESTS_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST, ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS, ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST_FAILED, REJECT_ARBITRATOR_REQUEST, REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS, REJECT_ARBITRATOR_REQUEST_SUCCEEDED, REJECT_ARBITRATOR_REQUEST_FAILED
|
||||
} from './constants';
|
||||
import OwnedUpgradeabilityProxy from '../../../embarkArtifacts/contracts/OwnedUpgradeabilityProxy';
|
||||
Escrow.options.address = OwnedUpgradeabilityProxy.options.address;
|
||||
|
@ -116,6 +117,31 @@ export function *onLoadArbitration() {
|
|||
yield takeEvery(LOAD_ARBITRATION, doLoadArbitration);
|
||||
}
|
||||
|
||||
export function *onGetArbitratorApprovalRequests() {
|
||||
yield takeEvery(GET_ARBITRATION_REQUESTS, doGetArbitratorApprovalRequests);
|
||||
}
|
||||
|
||||
export function *doGetArbitratorApprovalRequests({address}) {
|
||||
try {
|
||||
const events = yield ArbitrationLicense.getPastEvents('ArbitratorRequested', {fromBlock: 1, filter: {arbitrator: address} });
|
||||
const requests = yield all(events.map(function *(event) {
|
||||
const request = event.returnValues;
|
||||
const requestDetail = yield ArbitrationLicense.methods.requests(request.id).call();
|
||||
|
||||
if([NONE, CLOSED].indexOf(requestDetail.status) > -1) return null;
|
||||
|
||||
request.status = requestDetail.status;
|
||||
return request;
|
||||
}));
|
||||
|
||||
yield put({type: GET_ARBITRATION_REQUESTS_SUCCEEDED, requests: requests.filter(x => x !== null)});
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
yield put({type: GET_ARBITRATION_REQUESTS_FAILED, error: error.message});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function *doBuyLicense() {
|
||||
try {
|
||||
|
@ -197,6 +223,14 @@ export function *onChangeAcceptAll() {
|
|||
yield takeEvery(CHANGE_ACCEPT_EVERYONE, doTransaction.bind(null, CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE_SUCCEEDED, CHANGE_ACCEPT_EVERYONE_FAILED));
|
||||
}
|
||||
|
||||
export function *onAcceptRequest() {
|
||||
yield takeEvery(ACCEPT_ARBITRATOR_REQUEST, doTransaction.bind(null, ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS, ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST_FAILED));
|
||||
}
|
||||
|
||||
export function *onRejectRequest() {
|
||||
yield takeEvery(REJECT_ARBITRATOR_REQUEST, doTransaction.bind(null, REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS, REJECT_ARBITRATOR_REQUEST_SUCCEEDED, REJECT_ARBITRATOR_REQUEST_FAILED));
|
||||
}
|
||||
|
||||
export default [
|
||||
fork(onGetEscrows),
|
||||
fork(onResolveDispute),
|
||||
|
@ -209,5 +243,8 @@ export default [
|
|||
fork(onCancelDispute),
|
||||
fork(onRequestArbitrator),
|
||||
fork(onCancelArbitratorRequest),
|
||||
fork(onChangeAcceptAll)
|
||||
fork(onChangeAcceptAll),
|
||||
fork(onGetArbitratorApprovalRequests),
|
||||
fork(onAcceptRequest),
|
||||
fork(onRejectRequest)
|
||||
];
|
||||
|
|
|
@ -27,3 +27,5 @@ export const isLicenseOwner = state => state.arbitration.licenseOwner;
|
|||
export const acceptsEveryone = state => state.arbitration.acceptAny;
|
||||
export const isLoading = state => state.arbitration.loading;
|
||||
export const getLicensePrice = state => parseInt(state.arbitration.price, 10);
|
||||
|
||||
export const getArbitratorRequests = state => state.arbitration.arbitratorRequests;
|
||||
|
|
|
@ -11,6 +11,7 @@ import Loading from '../../components/Loading';
|
|||
import ErrorInformation from '../../components/ErrorInformation';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import { formatArbitratorName } from '../../utils/strings';
|
||||
|
||||
class Arbitrators extends Component {
|
||||
constructor(props) {
|
||||
|
@ -21,7 +22,7 @@ class Arbitrators extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if ((!prevProps.arbitrators && this.props.arbitrators) || prevProps.arbitrators.length !== this.props.arbitrators.length || Object.keys(this.props.users).length < this.props.arbitrators.length) {
|
||||
if ((!prevProps.arbitrators && this.props.arbitrators) || Object.keys(prevProps.arbitrators).length !== Object.keys(this.props.arbitrators).length || Object.keys(this.props.users).length === Object.keys(this.props.arbitrators).length) {
|
||||
Object.keys(this.props.arbitrators).forEach(arbitratorAddr => {
|
||||
if (!this.props.users[arbitratorAddr] && !this.loadedUsers.includes(arbitratorAddr)) {
|
||||
this.props.getUser(arbitratorAddr);
|
||||
|
@ -56,12 +57,15 @@ class Arbitrators extends Component {
|
|||
const isUser = addressCompare(address, arb);
|
||||
const enableDate = parseInt(arbitrators[arb].request.date, 10) + (86400 * 3) + 20;
|
||||
const isDisabled = (Date.now() / 1000) < enableDate;
|
||||
|
||||
const text = formatArbitratorName(users[arb], arb) + (isUser ? " (You)" : "");
|
||||
|
||||
return <ListGroupItem key={i}>
|
||||
<Row>
|
||||
<Col xs="12" sm="9" className="pb-3">
|
||||
<span className="text-small">{arb}</span>
|
||||
<br />
|
||||
<span className={classnames("font-weight-bold", {'text-success': isUser})}>{(users[arb] && users[arb].username ? users[arb].username : "Arbitrator has no username") + (isUser ? " (You)" : "") }</span>
|
||||
<span className={classnames("font-weight-bold", {'text-success': isUser})}>{text}</span>
|
||||
</Col>
|
||||
<Col xs="12" sm="3" className="text-center">
|
||||
{ !isUser && !arbitrators[arb].isAllowed && [arbitration.constants.NONE, arbitration.constants.REJECTED, arbitration.constants.CLOSED].indexOf(arbitrators[arb].request.status) > -1 && <Button disabled={isDisabled} onClick={this.requestArbitrator(arb)}>Request</Button> }
|
||||
|
|
|
@ -40,6 +40,7 @@ class MyProfile extends Component {
|
|||
componentDidMount() {
|
||||
this.props.loadProfile(this.props.address);
|
||||
this.props.getDisputedEscrows();
|
||||
this.props.getArbitratorRequests();
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps){
|
||||
|
@ -65,7 +66,7 @@ class MyProfile extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {profile, address, deleteOfferStatus, txHash} = this.props;
|
||||
const {profile, address, deleteOfferStatus, txHash, requests} = this.props;
|
||||
if(!profile) return <Loading page={true} />;
|
||||
|
||||
if(deleteOfferStatus === States.pending) {
|
||||
|
@ -80,12 +81,16 @@ class MyProfile extends Component {
|
|||
return x;
|
||||
});
|
||||
|
||||
const pendingRequests = requests.reduce((a, b) => {
|
||||
return a + (b.status === arbitration.constants.AWAIT ? 1 : 0);
|
||||
}, 0);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<UserInformation isArbitrator={profile.isArbitrator} reputation={profile.reputation} identiconSeed={profile.statusContactCode} username={profile.username}/>
|
||||
|
||||
{profile.isArbitrator && <Fragment>
|
||||
<Link to={"/sellers"}>Seller Management (TODO: Add number of pending requests)</Link>
|
||||
<Link to={"/sellers"}>Seller Management {pendingRequests > 0 && <span className="text-warining">({pendingRequests} pending requests)</span>}</Link>
|
||||
<Disputes disputes={this.props.disputes.filter(x => x.arbitration.open && !addressCompare(x.seller, address) && !addressCompare(x.buyer, address) && addressCompare(x.arbitrator, address))} open={true} showDate={true} />
|
||||
<Disputes disputes={this.props.disputes.filter(x => !x.arbitration.open && !addressCompare(x.seller, address) && !addressCompare(x.buyer, address) && addressCompare(x.arbitrator, address))} open={false} showDate={false} />
|
||||
</Fragment>}
|
||||
|
@ -115,7 +120,9 @@ MyProfile.propTypes = {
|
|||
watchEscrow: PropTypes.func,
|
||||
deleteOffer: PropTypes.func,
|
||||
deleteOfferStatus: PropTypes.string,
|
||||
txHash: PropTypes.string
|
||||
txHash: PropTypes.string,
|
||||
requests: PropTypes.array,
|
||||
getArbitratorRequests: PropTypes.func
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
|
@ -128,7 +135,8 @@ const mapStateToProps = state => {
|
|||
disputes: arbitration.selectors.escrows(state),
|
||||
escrowEvents: events.selectors.getEscrowEvents(state),
|
||||
deleteOfferStatus: metadata.selectors.getDeleteOfferStatus(state),
|
||||
txHash: metadata.selectors.txHash(state)
|
||||
txHash: metadata.selectors.txHash(state),
|
||||
requests: arbitration.selectors.getArbitratorRequests(state)
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -138,5 +146,6 @@ export default connect(
|
|||
loadProfile: metadata.actions.load,
|
||||
getDisputedEscrows: arbitration.actions.getDisputedEscrows,
|
||||
watchEscrow: escrow.actions.watchEscrow,
|
||||
deleteOffer: metadata.actions.deleteOffer
|
||||
deleteOffer: metadata.actions.deleteOffer,
|
||||
getArbitratorRequests: arbitration.actions.getArbitratorRequests
|
||||
})(withRouter(MyProfile));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {withRouter} from "react-router-dom";
|
||||
import {withRouter, Link} from "react-router-dom";
|
||||
import network from '../../features/network';
|
||||
import arbitration from '../../features/arbitration';
|
||||
import metadata from '../../features/metadata';
|
||||
|
@ -8,20 +8,51 @@ import Loading from '../../components/Loading';
|
|||
import ErrorInformation from '../../components/ErrorInformation';
|
||||
import PropTypes from 'prop-types';
|
||||
import BootstrapSwitchButton from 'bootstrap-switch-button-react';
|
||||
import { ListGroup, ListGroupItem, Button, Row, Col } from 'reactstrap';
|
||||
import classnames from 'classnames';
|
||||
import { formatArbitratorName } from '../../utils/strings';
|
||||
|
||||
const requestStatus = {
|
||||
[arbitration.constants.AWAIT]: "Pending",
|
||||
[arbitration.constants.ACCEPTED]: "Accepted",
|
||||
[arbitration.constants.REJECTED]: "Rejected"
|
||||
};
|
||||
|
||||
class SellerApproval extends Component {
|
||||
|
||||
componentDidMount(){
|
||||
this.props.checkLicenseOwner();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
props.checkLicenseOwner();
|
||||
props.getArbitratorRequests();
|
||||
this.loadedUsers = [];
|
||||
}
|
||||
|
||||
onToggleCheckbox = (checked) => {
|
||||
this.props.changeAcceptEveryone(checked);
|
||||
}
|
||||
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if ((!prevProps.requests && this.props.requests) || prevProps.requests.length !== this.props.requests) {
|
||||
this.props.requests.map(x => x.seller).forEach(seller => {
|
||||
if (!this.props.users[seller] && !this.loadedUsers.includes(seller)) {
|
||||
this.props.getUser(seller);
|
||||
this.loadedUsers.push(seller);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
acceptRequest = id => () => {
|
||||
this.props.acceptRequest(id);
|
||||
}
|
||||
|
||||
rejectRequest = id => () => {
|
||||
this.props.rejectRequest(id);
|
||||
}
|
||||
|
||||
render(){
|
||||
const {loading, error, txHash, cancelArbitratorsActions, profile, acceptsEveryone} = this.props;
|
||||
const {loading, error, txHash, cancelArbitratorsActions, profile, acceptsEveryone, requests, users} = this.props;
|
||||
if(error) {
|
||||
return <ErrorInformation transaction message={error} cancel={cancelArbitratorsActions}/>;
|
||||
}
|
||||
|
@ -37,9 +68,39 @@ class SellerApproval extends Component {
|
|||
<h2 className="mb-4">Seller Management</h2>
|
||||
<h3 className="mb-2">Accept all sellers</h3>
|
||||
{<BootstrapSwitchButton onlabel="ON" offlabel="OFF" checked={acceptsEveryone} onChange={this.onToggleCheckbox}/>}
|
||||
|
||||
<p><br /><br /><br />TODO: show list of requests for arbitrator</p>
|
||||
|
||||
{ !acceptsEveryone && <Fragment>
|
||||
<h3 className="mb-2 mt-5">Requests for arbitrator</h3>
|
||||
<ListGroup>
|
||||
{requests.map((request, i) => {
|
||||
const text = formatArbitratorName(users[request.seller], request.seller);
|
||||
|
||||
return <ListGroupItem key={i}>
|
||||
<Row>
|
||||
<Col xs="12" sm="9" className="pb-3" tag={Link} to={`/profile/${request.seller}`}>
|
||||
<span className="text-small">{request.seller}</span>
|
||||
<br />
|
||||
<span className={classnames("font-weight-bold")}>{text}</span>
|
||||
</Col>
|
||||
<Col xs="12" sm="3" className="text-center">
|
||||
{request.status === arbitration.constants.AWAIT && <Button onClick={this.acceptRequest(request.id)} className="m-2">Accept</Button> }
|
||||
{(request.status === arbitration.constants.AWAIT || request.status === arbitration.constants.ACCEPTED) && <Button className="m-2" onClick={this.rejectRequest(request.id)}>Reject</Button> }
|
||||
<p className={classnames('text-small', {
|
||||
'text-success': request.status === arbitration.constants.ACCEPTED,
|
||||
'text-danger': request.status === arbitration.constants.REJECTED,
|
||||
'text-muted': request.status === arbitration.constants.AWAIT
|
||||
})}>
|
||||
({requestStatus[request.status]})
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</ListGroupItem>;
|
||||
}
|
||||
)}
|
||||
</ListGroup>
|
||||
</Fragment>
|
||||
}
|
||||
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -55,7 +116,13 @@ SellerApproval.propTypes = {
|
|||
changeAcceptEveryone: PropTypes.func,
|
||||
checkLicenseOwner: PropTypes.func,
|
||||
acceptsEveryone: PropTypes.bool,
|
||||
profile: PropTypes.object
|
||||
profile: PropTypes.object,
|
||||
requests: PropTypes.array,
|
||||
getArbitratorRequests: PropTypes.func,
|
||||
getUser: PropTypes.func,
|
||||
users: PropTypes.object,
|
||||
acceptRequest: PropTypes.func,
|
||||
rejectRequest: PropTypes.func
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,8 +134,10 @@ const mapStateToProps = state => {
|
|||
error: arbitration.selectors.errorGet(state),
|
||||
txHash: arbitration.selectors.txHash(state),
|
||||
profile: metadata.selectors.getProfile(state, address) ,
|
||||
acceptsEveryone: arbitration.selectors.acceptsEveryone(state)
|
||||
};
|
||||
acceptsEveryone: arbitration.selectors.acceptsEveryone(state),
|
||||
requests: arbitration.selectors.getArbitratorRequests(state),
|
||||
users: metadata.selectors.getAllUsers(state)
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
@ -76,5 +145,9 @@ export default connect(
|
|||
{
|
||||
cancelArbitratorsActions: arbitration.actions.cancelArbitratorActions,
|
||||
changeAcceptEveryone: arbitration.actions.changeAcceptEveryone,
|
||||
checkLicenseOwner: arbitration.actions.checkLicenseOwner
|
||||
checkLicenseOwner: arbitration.actions.checkLicenseOwner,
|
||||
getArbitratorRequests: arbitration.actions.getArbitratorRequests,
|
||||
getUser: metadata.actions.loadUserOnly,
|
||||
acceptRequest: arbitration.actions.acceptRequest,
|
||||
rejectRequest: arbitration.actions.rejectRequest
|
||||
})(withRouter(SellerApproval));
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
export const formatArbitratorName = (user, address, noUsernameLabel, index) => {
|
||||
if (!user) return address + ' - Loading...';
|
||||
return `${index >= 0 ? index + 1 + ' - ' : ""}${user.username || (noUsernameLabel ? noUsernameLabel : "No username available") }${user.location ? ' from ' + user.location : ''} - ${user.upCount || 0}↑ ${user.downCount || 0}↓`;
|
||||
};
|
|
@ -5,6 +5,8 @@ import {Typeahead} from 'react-bootstrap-typeahead';
|
|||
import {withNamespaces, Trans} from 'react-i18next';
|
||||
import {compactAddress} from '../../../../utils/address';
|
||||
import {Link} from "react-router-dom";
|
||||
import {formatArbitratorName} from '../../../../utils/strings';
|
||||
|
||||
|
||||
class ArbitratorSelectorForm extends Component {
|
||||
onChange = (items) => {
|
||||
|
@ -22,12 +24,8 @@ class ArbitratorSelectorForm extends Component {
|
|||
const arbitratorStrings = this.props.arbitrators.map((arbitratorAddr, index) => {
|
||||
const user = this.props.users[arbitratorAddr];
|
||||
|
||||
let text;
|
||||
if (!user) {
|
||||
text = arbitratorAddr + ' - Loading...';
|
||||
} else {
|
||||
text = `${index} - ${user.username || compactAddress(arbitratorAddr, 3)}${user.location ? ' from ' + user.location : ''} - ${user.upCount || 0}↑ ${user.downCount || 0}↓`;
|
||||
}
|
||||
let text = formatArbitratorName(user, arbitratorAddr, compactAddress(arbitratorAddr, 3), index);
|
||||
|
||||
if (value && value === arbitratorAddr) {
|
||||
defaultSelectedValue.push(text);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class SelectArbitrator extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if ((!prevProps.arbitrators && this.props.arbitrators) || prevProps.arbitrators.length !== this.props.arbitrators.length || Object.keys(this.props.users).length !== this.props.arbitrators.length) {
|
||||
if ((!prevProps.arbitrators && this.props.arbitrators) || prevProps.arbitrators.length !== this.props.arbitrators.length || Object.keys(this.props.users).length !== Object.keys(this.props.arbitrators).length) {
|
||||
Object.keys(this.props.arbitrators).forEach(arbitratorAddr => {
|
||||
if (!this.props.users[arbitratorAddr] && !this.loadedUsers.includes(arbitratorAddr)) {
|
||||
this.props.getUser(arbitratorAddr);
|
||||
|
|
Loading…
Reference in New Issue