Skip to content
This repository was archived by the owner on Sep 20, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions src/components/job.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import agentAbi from 'singularitynet-platform-contracts/abi/Agent.json';
import jobAbi from 'singularitynet-platform-contracts/abi/Job.json';
import Eth from 'ethjs';
import {Layout, Divider, Card, Icon, Spin, Alert, Row, Col, Button, Tag, message, Table, Collapse, Steps, Modal, Upload} from 'antd';
import {Layout, Divider, Card, Icon, Spin, Alert, Row, Col, Button, Tag, message, Table, Collapse, Steps, Modal, Upload, Popconfirm} from 'antd';
import { NETWORKS, ERROR_UTILS, AGENT_STATE, AGI } from '../util';
import {JsonRpcClient} from "../jsonrpc";
import abiDecoder from 'abi-decoder';
Expand Down Expand Up @@ -96,6 +96,7 @@ class Job extends React.Component {
}));

this.nextJobStep();
this.props.sendJobInProgress(true);
}
});
}).catch(this.handleReject);
Expand Down Expand Up @@ -204,7 +205,7 @@ class Job extends React.Component {

return receipt;
}

render() {

let modal = type =>
Expand Down Expand Up @@ -359,13 +360,24 @@ class Job extends React.Component {
// Display service specific form submission or results display for the last two steps
(this.state.jobStep >= (steps.length - 2)) &&
<React.Fragment>
<div>
<Divider orientation="left">Service Call</Divider>
<CallComponent callModal={serviceModal} showModalCallback={this.showModal} callApiCallback={this.callApi} jobResult={this.state.jobResult}/>
</div>
<div>
<Divider orientation="left">Service Call</Divider>
<CallComponent callModal={serviceModal} showModalCallback={this.showModal} callApiCallback={this.callApi} jobResult={this.state.jobResult}/>
</div>
</React.Fragment>
}
{
// Display a button that allows the user to end the job, clear the data and possibly choose another job
(this.state.jobStep >= (steps.length - 1)) &&
<React.Fragment>
<div align="center">
<Divider type="horizontal"/>
<Popconfirm title="Are you sure you want to end this job? This will clear all the data from the interface." onConfirm={() => this.props.sendJobInProgress(false)} okText="Yes" cancelText="No">
<Button type="primary">End Job</Button>
</Popconfirm>
</div>
</React.Fragment>
}

</Card>
</React.Fragment>
);
Expand Down
69 changes: 64 additions & 5 deletions src/components/services.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import Eth from 'ethjs';
import {Layout, Divider, Card, Icon, Spin, Alert, Row, Col, Button, Tag, message, Table} from 'antd';
import {Input, Divider, Card, Icon, Button, Tag, Table} from 'antd';
import {NETWORKS, AGENT_STATE, AGI, FORMAT_UTILS, STRINGS} from '../util';


Expand All @@ -11,14 +11,34 @@ class Services extends React.Component {

this.state = {
agents : [],
selectedAgent: undefined,
};

this.servicesTableKeys = [
{
title: 'Agent',
dataIndex: 'name',
width: 200,
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => this.renderFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters }),
filterIcon: filtered => <Icon type="search" theme="outlined" style={{ color: filtered ? '#108ee9' : '#aaa' }} />,
onFilter: (value, record) => record.name.toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: (visible) => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
});
}
},
render: (text) => {
const { searchText } = this.state;
return searchText ? (
<span>
{text.split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i')).map((fragment, i) => (
fragment.toLowerCase() === searchText.toLowerCase()
? <span key={i} style={{color:'#20AAF8'}} className="highlight">{fragment}</span> : fragment // eslint-disable-line
))}
</span>
) : text;
},
},
{
title: 'Contract Address',
Expand Down Expand Up @@ -46,18 +66,30 @@ class Services extends React.Component {
title: '',
dataIndex: 'state',
render: (state, agent, index) =>
<Button type={state == AGENT_STATE.ENABLED ? 'primary' : 'danger'} disabled={ !(state == AGENT_STATE.ENABLED) || typeof this.props.account === 'undefined' || typeof this.state.selectedAgent !== 'undefined' } onClick={() => { this.setState({ selectedAgent: agent }); return this.props.onAgentClick(agent); }} >
{ this.getAgentButtonText(state, agent) }
<Button type={state == AGENT_STATE.ENABLED ? 'primary' : 'danger'}
onClick={() => { return this.props.onAgentClick(agent); }}
disabled={ !(state == AGENT_STATE.ENABLED)
|| typeof this.props.account === 'undefined'
|| this.props.jobInProgress
|| this.isSelectedAgent(agent)}>
{this.getAgentButtonText(state, agent) }
</Button>
}
].map(column => Object.assign({}, { width: 150 }, column));

this.watchRegistriesTimer = undefined;
}

isSelectedAgent(agent){
if (this.props.selectedAgent !== undefined) {
return this.props.selectedAgent.key === agent.key;
}
return false;
}

getAgentButtonText(state, agent) {
if (this.props.account) {
if (typeof this.state.selectedAgent === 'undefined' || this.state.selectedAgent.key !== agent.key) {
if (typeof this.props.selectedAgent === 'undefined' || this.props.selectedAgent.key !== agent.key) {
return state == AGENT_STATE.ENABLED ? 'Create Job' : 'Agent Disabled';
} else {
return 'Selected';
Expand Down Expand Up @@ -197,6 +229,33 @@ class Services extends React.Component {
}
}

handleSearch(selectedKeys, confirm) {
this.setState({ searchText: selectedKeys[0] })
return confirm()
}

handleReset(clearFilters){
this.setState({ searchText: '' });
return clearFilters()
}

renderFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters }){
return (
<div className="custom-filter-dropdown" style ={{padding: '8px', borderRadius: '6px', background: '#fff', boxShadow: '0 1px 6px rgba(0, 0, 0, .2)'}}>
<Input
style={{width: '130px', marginRight: '8px'}}
ref={ele => this.searchInput = ele}
placeholder="Search name"
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
/>
<Button type="primary" onClick={() => this.handleSearch(selectedKeys, confirm)}>Search</Button>
<Button onClick={() => this.handleReset(clearFilters)}>Reset</Button>
</div>
)
}

render() {

let servicesTable = (columns, dataSource, featured) =>
Expand Down
20 changes: 17 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class App extends React.Component {
selectedAgent: undefined,
agentCallComponent: undefined,
usingDefaultCallComponent: false,
jobInProgress: false,
};

this.serviceNameToComponent = {
Expand All @@ -44,7 +45,7 @@ class App extends React.Component {
'face_landmarks': FaceLandmarksService,
'face_alignment': FaceAlignmentService,
'face_recognition': FaceRecognitionService,
'Exchange AGI for BTC': ExchangeService
'Exchange AGI for BTC': ExchangeService,
};
this.serviceDefaultComponent = DefaultService;

Expand Down Expand Up @@ -148,6 +149,19 @@ class App extends React.Component {
});
}

updateJobInProgress(jobInProgress) {
if (jobInProgress){
console.log("There is a job in progress");
this.setState({jobInProgress: true,})
} else {
console.log("No job in progress");
this.setState({selectedAgent: undefined,
agentCallComponent: undefined,
usingDefaultCallComponent: false,
jobInProgress: false,})
}
}

render() {

return (
Expand All @@ -161,14 +175,14 @@ class App extends React.Component {
<Col xs={24} sm={24} md={22} lg={15} xl={18} span={9}>
<Account network={this.state.chainId} account={this.state.account} ethBalance={this.state.ethBalance} agiBalance={this.state.agiBalance} />
<Divider/>
<Services account={this.state.account} network={this.state.chainId} registries={this.registryInstances} agentContract={this.agentContract} onAgentClick={(agent) => this.hireAgent(agent)} />
<Services account={this.state.account} network={this.state.chainId} registries={this.registryInstances} agentContract={this.agentContract} onAgentClick={(agent) => this.hireAgent(agent)} jobInProgress={this.state.jobInProgress} selectedAgent={this.state.selectedAgent} />
<Divider/>
{ this.state.usingDefaultCallComponent &&
<Alert type="warning" message="This service is using the default interface" description="You will have to marshall the data into JSON-RPC yourself and ensure it matches the API of the service based on its documentation."/>
}
{
this.state.selectedAgent && this.state.chainId && this.state.account &&
<Job network={this.state.chainId} account={this.state.account} agent={this.state.selectedAgent} callComponent={this.state.serviceCallComponent} token={this.tokenInstance} />
<Job network={this.state.chainId} account={this.state.account} agent={this.state.selectedAgent} callComponent={this.state.serviceCallComponent} token={this.tokenInstance} sendJobInProgress={(jobInProgress) => this.updateJobInProgress(jobInProgress)} />
}
</Col>
</Row>
Expand Down