Finished implementation

This commit is contained in:
Daniel Gonzalez
2021-08-24 12:08:03 -04:00
parent 32d23bb0dc
commit 937219a8c6
4 changed files with 234 additions and 63 deletions
+127
View File
@@ -0,0 +1,127 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Row, Col, Box, Button } from 'adminlte-2-react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
let _this
class Details extends React.Component {
constructor (props) {
super(props)
_this = this
this.state = {
entry: {},
entryData: {}
}
}
render () {
const { entry, entryData } = _this.state
return (
<>
<Row>
<Col sm={12}>
<Box className=' border-none mt-2' loaded={!this.state.inFetch}>
<Row className='text-center'>
<Col sm={12}>
<h1 id='SendTokens'>
<FontAwesomeIcon
className='title-icon'
size='xs'
icon='info-circle'
/>
<span>Details</span>
</h1>
{entry._id && (
<Box className='border-none details-data-content'>
<p>
<b>IS VALID: </b>
{entry.isValid}
</p>
<p>
<b>APP ID: </b>
{entry.appId || 'none'}
</p>
<p>
<b>CREATE AT: </b>
{new Date(entry.createdAt).toLocaleString()}
</p>
<p>
<b>ID: </b>
{entry._id}
</p>
<p>
<b>HASH: </b>
{entry.hash}
</p>
<p>
<b>TRANSACTION ID : </b>
{entry.key}
</p>
{entryData && (
<>
<b>VALUE : </b>
<p>
- <b>Message : </b> {entryData.message}
</p>
<p>
- <b>Signature : </b> {entryData.signature}
</p>
<p>
- <b>Data : </b> {entryData.data}
</p>
</>
)}
</Box>
)}
</Col>
<Col sm={12}>
<div className='btn-wrapper'>
<Button
text='Close'
type='primary'
className='btn-lg btn-close-entry mr-1 ml-1 mt-1'
onClick={_this.handleClose}
/>
</div>
</Col>
</Row>
</Box>
</Col>
</Row>
</>
)
}
componentDidMount () {
_this.handleData()
}
componentDidUpdate () {
if (_this.props.entry._id !== _this.state.entry._id) {
_this.handleData()
}
}
handleData () {
try {
const { entry } = _this.props
_this.setState({
entry,
entryData: entry.value
})
} catch (err) {
console.warn('Error in handleData()', err)
}
}
handleClose () {
_this.props.onClose()
}
}
Details.propTypes = {
entry: PropTypes.object,
onClose: PropTypes.func
}
export default Details
+10
View File
@@ -0,0 +1,10 @@
.btn-close-entry{
width: 150px;
}
.action-handler{
color: #3c8dbc;
cursor: pointer;
}
.details-data-content{
text-align: left;
}
+97 -62
View File
@@ -1,5 +1,7 @@
import React from 'react' import React from 'react'
import { Row, Col, Content, Box, DataTable } from 'adminlte-2-react' import { Row, Col, Content, Box, DataTable } from 'adminlte-2-react'
import Details from './details'
import './explorer.css'
const axios = require('axios').default const axios = require('axios').default
const SERVER = 'https://p2wdb.fullstack.cash/' const SERVER = 'https://p2wdb.fullstack.cash/'
@@ -11,36 +13,38 @@ class Explorer extends React.Component {
super(props) super(props)
_this = this _this = this
this.state = { this.state = {
showEntry: false,
data: [], data: [],
firstColumns: [ entries: [],
{ title: 'Created At', data: 'createdAt' }, entryData: null
{
title: 'Transaction ID',
data: 'txid',
render: txid => <span id={txid.subString}>{txid.subString}</span>
},
{
title: 'Hash',
data: 'hash',
render: hash => (
<span
onclick={() => {
console.log('test')
}}
id={hash.subString}
>
{hash.subString}
</span>
)
},
{ title: 'App Id', data: 'appId' }
],
entries: []
} }
this.firstColumns = [
{ title: 'Created At', data: 'createdAt' },
{
title: 'Transaction',
data: 'txid',
render: txid => (
<span className='on-click-event action-handler'>
{txid.subString}
</span>
)
},
{
title: 'Hash',
data: 'hash',
render: hash => (
<span className='on-click-event action-handler'>
{hash.subString}
</span>
)
},
{ title: 'App Id', data: 'appId' }
]
} }
render () { render () {
const { data, firstColumns } = _this.state const { data, entryData } = _this.state
return ( return (
<Content <Content
title='P2WDB Explorer' title='P2WDB Explorer'
@@ -48,20 +52,29 @@ class Explorer extends React.Component {
browserTitle='P2WDB Explorer' browserTitle='P2WDB Explorer'
> >
<Row> <Row>
{entryData && (
<Col xs={12}>
<Details entry={entryData} onClose={_this.handleClose} />
</Col>
)}
<Col xs={12}> <Col xs={12}>
<Box title='Block explorer for P2WDB'> <Box title='Block explorer for P2WDB'>
<DataTable <DataTable
columns={firstColumns} columns={_this.firstColumns}
data={data} data={data}
options={{ options={{
paging: true, paging: true,
lengthChange: false, lengthChange: false,
searching: false, searching: false,
ordering: true, ordering: false,
info: true, info: true,
autoWidth: true autoWidth: false
}}
onClickEvents={{
onClickEvent: (data, rowIdx, rowData) => {
_this.handleEvents(data)
}
}} }}
onPageChange={_this.handleEvents}
/> />
</Box> </Box>
</Col> </Col>
@@ -71,14 +84,18 @@ class Explorer extends React.Component {
} }
async componentDidMount () { async componentDidMount () {
const entries = await _this.getEntries() _this.handleEntries()
_this.generateDataTable(entries)
// Get data and update table
// every 20 seconds
setInterval(() => {
_this.handleEntries()
}, 20000)
} }
async componentDidUpdate () { async handleEntries () {
// Adds new 'click' events when the view is updated const entries = await _this.getEntries()
const { entries } = _this.state _this.generateDataTable(entries)
_this.handleEvents(entries)
} }
// REST petition to Get data fron the pw2db // REST petition to Get data fron the pw2db
@@ -90,7 +107,6 @@ class Explorer extends React.Component {
data: {} data: {}
} }
const result = await axios.request(options) const result = await axios.request(options)
console.log('result', result.data)
_this.setState({ _this.setState({
entries: result.data.data entries: result.data.data
}) })
@@ -100,22 +116,29 @@ class Explorer extends React.Component {
} }
} }
// Generate table content
generateDataTable (dataArr) { generateDataTable (dataArr) {
try { try {
const data = [] const data = []
for (let i = 0; i < dataArr.length; i++) { for (let i = 0; i < dataArr.length; i++) {
const entry = dataArr[i] const entry = dataArr[i]
const row = { const row = {
createdAt: entry.createdAt, // createdAt row data
createdAt: new Date(entry.createdAt).toLocaleString(),
// Transaction id row data
txid: { txid: {
subString: _this.simplifyString(entry.key), subString: _this.cutString(entry.key),
value: entry.key txid: entry.key
}, },
// Hash row data
hash: { hash: {
subString: _this.simplifyString(entry.hash), subString: _this.cutString(entry.hash),
value: entry.hash hash: entry.hash,
data: entry
}, },
appId: entry.appId // App id row data
appId: entry.appId || 'none'
} }
data.push(row) data.push(row)
} }
@@ -127,46 +150,58 @@ class Explorer extends React.Component {
} }
} }
simplifyString (txid) { cutString (txid) {
try { try {
const subTxid = txid.slice(0, 4) const subTxid = txid.slice(0, 4)
const subTxid2 = txid.slice(-4) const subTxid2 = txid.slice(-4)
return `${subTxid}...${subTxid2}` return `${subTxid}...${subTxid2}`
} catch (err) { } catch (err) {
console.warn('Error in cutTxid() ', err) console.warn('Error in cutString() ', err)
} }
} }
handleTxId (txid) { handleTxIdClick (txid) {
try { try {
window.open(`${EXPLORER_URL}${txid}`, '_blank') window.open(`${EXPLORER_URL}${txid}`, '_blank')
} catch (err) { } catch (err) {
console.warn('Error in handleTxId() ', err) console.warn('Error in handleTxIdClick() ', err)
} }
} }
// Gets each element of the transaction id column handleHashClick (data) {
// to add them the onClick event, its done this way
// because that event is not recognized if it gets
// added directly to the html tag
handleEvents () {
try { try {
const { entries } = _this.state data.isValid = data.isValid.toString()
for (let i = 0; i < entries.length; i++) { _this.setState({
const entry = entries[i] entryData: data
const txid = _this.simplifyString(entry.key) })
const element = document.getElementById(txid) } catch (err) {
if (element) { _this.setState({
// Adding on click event entryData: null
element.addEventListener('click', () => { })
_this.handleTxId(entry.key) console.warn('Error in handleHashClick() ', err)
}) }
} }
handleEvents (eventData) {
try {
const { txid, hash, data } = eventData
if (txid) {
_this.handleTxIdClick(txid)
}
if (hash && data) {
_this.handleHashClick(data)
} }
} catch (err) { } catch (err) {
console.warn('Error in handleEvents() ', err) console.warn('Error in handleEvents() ', err)
} }
} }
handleClose () {
_this.setState({
entryData: null
})
}
} }
export default Explorer export default Explorer
@@ -31,7 +31,6 @@ const { Item } = Sidebar
const MenuComponents = props => { const MenuComponents = props => {
return [ return [
{ {
activedItem: true,
key: 'Explorer', key: 'Explorer',
component: <Explorer key='Explorer' {...props} />, component: <Explorer key='Explorer' {...props} />,
menuItem: <Item icon='fas-binoculars' key='Explorer' text='Explorer' /> menuItem: <Item icon='fas-binoculars' key='Explorer' text='Explorer' />