diff --git a/frontend/src/components/LookupDevice.js b/frontend/src/components/LookupDevice.js
new file mode 100644
index 0000000..42da3e1
--- /dev/null
+++ b/frontend/src/components/LookupDevice.js
@@ -0,0 +1,56 @@
+import React, { Component } from 'react';
+import ManageDevice from './ManageDevice';
+
+import { Input, Divider } from 'antd';
+
+const { Search } = Input;
+
+class LookupDevice extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ match: {
+ params: {
+ deviceId: 1
+ }
+ },
+ searched: false
+ }
+ }
+
+ lookupDevice(value) {
+ this.setState({
+ match: {
+ params: {
+ deviceId: value
+ }
+ },
+ searched: true
+ })
+ }
+
+ render() {
+ return (
+
+
+ Search for any device.
+
+
this.lookupDevice(value)}
+ size="large"
+ enterButton
+ />
+ {this.state.searched &&
+
+ }
+
+ )
+ }
+}
+
+export default LookupDevice;
\ No newline at end of file
diff --git a/frontend/src/components/LookupEntity.js b/frontend/src/components/LookupEntity.js
new file mode 100644
index 0000000..3859e04
--- /dev/null
+++ b/frontend/src/components/LookupEntity.js
@@ -0,0 +1,121 @@
+import DeviceManager, { getDefaultAccount } from '../DeviceManager';
+import ethUtil from 'ethereumjs-util';
+
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom';
+import { Button, Tag, Card, Input, Divider, Timeline, message } from 'antd';
+
+const Search = Input.Search;
+
+const eventsToSave = ['EntityDataUpdated', 'DeviceCreated', 'DeviceTransfered', 'DeviceSigned'];
+
+class LookupEntity extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ loading: false,
+ searchValue: '',
+ address: this.props.match.params.address,
+ data: [],
+ searched: false
+ }
+
+ this.lookupEntity = this.lookupEntity.bind(this);
+ }
+
+ componentWillMount() {
+ const { address } = this.state;
+ if (address != null) {
+ this.reloadWithAddress(address);
+ }
+ }
+
+ reloadWithAddress(address) {
+ this.setState({
+ searchValue: address
+ })
+ this.lookupEntity(address).then(() => { });
+ }
+
+ async lookupEntity(address) {
+ if (!ethUtil.isValidAddress(address)) {
+ message.error('Invalid entity address.');
+ return;
+ }
+
+ this.setState({
+ loading: true
+ });
+
+ try {
+ let instance = await DeviceManager;
+
+ let allEvents = instance.allEvents({ fromBlock: 0, toBlock: 'latest' });
+ allEvents.get((error, logs) => {
+ let filteredData = logs.filter(el => eventsToSave.includes(el.event) && (el.args.owner === address || el.args.oldOwner === address || el.args.newOwner === address || el.args.signer === address));
+ if (!error) {
+ this.setState({
+ address: address,
+ data: filteredData,
+ loading: false,
+ searched: true
+ })
+ }
+ });
+ } catch (error) {
+ console.log(error);
+ message.error(error.message);
+ }
+ }
+
+ render() {
+ return (
+
+
+ Search for any entity.
+
+
this.lookupEntity(value)}
+ size="large"
+ enterButton
+ value={this.state.searchValue}
+ onChange={(e) => this.setState({ searchValue: e.target.value })}
+ />
+
+ this.setState({ searchValue: getDefaultAccount() })}>Set to my address
+ {this.state.searched &&
+
+
+
+ {this.state.data.length !== 0 ?
+
+
Events that are filtered are {eventsToSave.join(', ')}
+
+ {this.state.data.map(el => {
+ if (el.event === 'EntityDataUpdated')
+ return Entity data updated to {el.args.newData}
+ if (el.event === 'DeviceCreated')
+ return Created device with ID {el.args.deviceId.toNumber()} , identifier {el.args.identifier}
, metadata hash {el.args.metadataHash}
and firmware hash {el.args.firmwareHash}
+ if (el.event === 'DeviceTransfered')
+ return Device with ID {el.args.deviceId.toNumber()} transfered {el.args.newOwner === this.state.address && from this.reloadWithAddress(el.args.oldOwner)}>{el.args.oldOwner} }{el.args.oldOwner === this.state.address && to this.reloadWithAddress(el.args.newOwner)}>{el.args.newOwner} }
+ if (el.event === 'DeviceSigned')
+ return Signed device with ID {el.args.deviceId.toNumber()}
+ else
+ return null
+ })}
+
+
+ :
+ empty
+ }
+
+
+ }
+
+ )
+ }
+}
+
+export default LookupEntity;
\ No newline at end of file