mirror of
https://github.com/fullstack-cash/explorer.fullstack.cash.git
synced 2026-09-21 16:52:05 -07:00
Finished implementation
This commit is contained in:
@@ -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
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.btn-close-entry{
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.action-handler{
|
||||||
|
color: #3c8dbc;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.details-data-content{
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
+97
-62
@@ -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' />
|
||||||
|
|||||||
Reference in New Issue
Block a user