Skip to content

Commit

Permalink
Merge pull request #272 from pshenmic/feat/validator-page
Browse files Browse the repository at this point in the history
Implement a new design for the specific validator page on the frontend
  • Loading branch information
pshenmic authored Oct 21, 2024
2 parents df16347 + 6ec454e commit f6a8209
Show file tree
Hide file tree
Showing 67 changed files with 2,698 additions and 363 deletions.
1 change: 1 addition & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"node-fetch": "^3.3.1",
"raw-loader": "^4.0.2",
"react": "^18.2.0",
"react-calendar": "^5.0.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1",
"react-paginate": "^8.2.0",
Expand Down
10 changes: 4 additions & 6 deletions packages/frontend/src/app/identity/[identifier]/Identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import TransactionsList from '../../../components/transactions/TransactionsList'
import DocumentsList from '../../../components/documents/DocumentsList'
import DataContractsList from '../../../components/dataContracts/DataContractsList'
import TransfersList from '../../../components/transfers/TransfersList'
import { fetchHandlerSuccess, fetchHandlerError, creditsToDash } from '../../../util'
import { fetchHandlerSuccess, fetchHandlerError } from '../../../util'
import { LoadingLine, LoadingList } from '../../../components/loading'
import { ErrorMessageBlock } from '../../../components/Errors'
import ImageGenerator from '../../../components/imageGenerator'
Expand Down Expand Up @@ -158,10 +158,8 @@ function Identity ({ identifier }) {
<Td isNumeric>
<LoadingLine loading={identity.loading}>
<RateTooltip
dash={creditsToDash(identity.data?.balance)}
usd={typeof rate.data?.usd === 'number'
? rate.data.usd * creditsToDash(identity.data?.balance)
: null}
credits={identity.data?.balance}
rate={rate.data}
>
<span><Credits>{identity.data?.balance}</Credits> Credits</span>
</RateTooltip>
Expand Down Expand Up @@ -254,7 +252,7 @@ function Identity ({ identifier }) {
<TabPanel px={0} h={'100%'}>
{!transactions.error
? !transactions.loading
? <TransactionsList transactions={transactions.data.resultSet} size={'m'}/>
? <TransactionsList transactions={transactions.data.resultSet}/>
: <LoadingList itemsCount={9}/>
: <ErrorMessageBlock/>}
</TabPanel>
Expand Down
8 changes: 3 additions & 5 deletions packages/frontend/src/app/transaction/[hash]/Transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import * as Api from '../../../util/Api'
import { useState, useEffect, useCallback } from 'react'
import { getTransitionTypeStringById, fetchHandlerSuccess, fetchHandlerError, creditsToDash } from '../../../util'
import { getTransitionTypeStringById, fetchHandlerSuccess, fetchHandlerError } from '../../../util'
import { Credits } from '../../../components/data'
import { LoadingLine, LoadingList } from '../../../components/loading'
import { ErrorMessageBlock } from '../../../components/Errors'
Expand Down Expand Up @@ -131,10 +131,8 @@ function Transaction ({ hash }) {
<Td>
<LoadingLine loading={transaction.loading}>
<RateTooltip
dash={creditsToDash(transaction.data?.gasUsed)}
usd={typeof rate.data?.usd === 'number'
? rate.data.usd * creditsToDash(transaction.data?.gasUsed)
: null}
credits={transaction.data?.gasUsed}
rate={rate.data}
>
<span><Credits>{transaction.data?.gasUsed}</Credits> Credits</span>
</RateTooltip>
Expand Down
132 changes: 118 additions & 14 deletions packages/frontend/src/app/validator/[hash]/BlocksChart.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,135 @@
import ProposedBlocksChart from './../../../components/charts/ProposedBlocksChart'
import { useState, useEffect, useRef } from 'react'
import { fetchHandlerSuccess, fetchHandlerError } from '../../../util'
import { useState, useEffect } from 'react'
import { LineChart, TimeframeMenu } from './../../../components/charts'
import * as Api from '../../../util/Api'
import { Button } from '@chakra-ui/react'
import { CalendarIcon } from './../../../components/ui/icons'
import { ErrorMessageBlock } from '../../../components/Errors'
import './TimeframeSelector.scss'
import './TabsChart.scss'

const chartConfig = {
timespan: {
default: '1w',
values: ['1h', '24h', '3d', '1w']
defaultIndex: 3,
values: [
{
label: '1 hour',
range: '1h'
},
{
label: '24 hours',
range: '24h'
},
{
label: '3 days',
range: '3d'
},
{
label: '1 week',
range: '1w'
}
]
}
}

export default function BlocksChart ({ hash }) {
const TimeframeSelector = ({ config, isActive, changeCallback, openStateCallback, menuRef }) => {
const [timespan, setTimespan] = useState(chartConfig.timespan.values[chartConfig.timespan.defaultIndex])
const [menuIsOpen, setMenuIsOpen] = useState(false)

const changeHandler = (value) => {
setTimespan(value)
if (typeof changeCallback === 'function') changeCallback(value)
setMenuIsOpen(false)
}

useEffect(() => {
if (!isActive) setMenuIsOpen(false)
}, [isActive])

useEffect(() => {
if (typeof openStateCallback === 'function') openStateCallback(menuIsOpen)
}, [menuIsOpen])

return (
<div className={`TimeframeSelector ${menuIsOpen ? 'TimeframeSelector--MenuActive' : ''}`}>
<TimeframeMenu
ref={menuRef}
className={'TimeframeSelector__Menu'}
config={config}
changeCallback={changeHandler}
/>

<Button
className={`TimeframeSelector__Button ${menuIsOpen ? 'TimeframeSelector__Button--Active' : ''}`}
onClick={() => setMenuIsOpen(state => !state)}
>
<CalendarIcon mr={'10px'}/>
{timespan.label}
</Button>
</div>
)
}

export default function BlocksChart ({ hash, isActive }) {
const [blocksHistory, setBlocksHistory] = useState({ data: {}, loading: true, error: false })
const [blocksHistoryTimespan, setBlocksHistoryTimespan] = useState(chartConfig.timespan.default)
const [timespan, setTimespan] = useState(chartConfig.timespan.values[chartConfig.timespan.defaultIndex])
const [menuIsOpen, setMenuIsOpen] = useState(false)
const TimeframeMenuRef = useRef(null)
const [selectorHeight, setSelectorHeight] = useState(0)

useEffect(() => {
Api.getBlocksStatsByValidator(hash, blocksHistoryTimespan)
Api.getBlocksStatsByValidator(hash, timespan.range)
.then(res => fetchHandlerSuccess(setBlocksHistory, { resultSet: res }))
.catch(err => fetchHandlerError(setBlocksHistory, err))
}, [blocksHistoryTimespan])
}, [timespan])

useEffect(() => {
if (menuIsOpen && TimeframeMenuRef.current) {
const element = TimeframeMenuRef.current
const height = element.getBoundingClientRect().height
setSelectorHeight(height)
} else {
setSelectorHeight(0)
}
}, [menuIsOpen, TimeframeMenuRef])

if (blocksHistory.error || (!blocksHistory.loading && !blocksHistory.data?.resultSet)) {
return (<ErrorMessageBlock/>)
}

return (
<ProposedBlocksChart
height={'100%'}
blocksHistory={blocksHistory}
timespan={blocksHistoryTimespan}
timespanChangeHandler={setBlocksHistoryTimespan}
/>
<div style={{ height: menuIsOpen ? `${Math.max(selectorHeight, 350)}px` : '350px' }} className={'TabsChart'}>
{!blocksHistory.loading &&
<TimeframeSelector
menuRef={TimeframeMenuRef}
className={'TabsChart__TimeframeSelector'}
config={chartConfig}
changeCallback={setTimespan}
isActive={isActive}
openStateCallback={setMenuIsOpen}
/>
}
<div className={`TabsChart__ChartContiner ${menuIsOpen ? 'TabsChart__ChartContiner--Hidden' : ''}`}>
<LineChart
data={blocksHistory.data?.resultSet?.map((item) => ({
x: new Date(item.timestamp),
y: item.data.blocksCount
})) || []}
timespan={timespan.range}
xAxis={{
type: (() => {
if (timespan.range === '1h') return { axis: 'time' }
if (timespan.range === '24h') return { axis: 'time' }
if (timespan.range === '3d') return { axis: 'date', tooltip: 'datetime' }
if (timespan.range === '1w') return { axis: 'date' }
})()
}}
yAxis={{
type: 'number',
abbreviation: 'blocks'
}}
/>
</div>
</div>
)
}
35 changes: 35 additions & 0 deletions packages/frontend/src/app/validator/[hash]/TabsChart.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.TabsChart {
height: 100%;
transition: all .2s;

&__ChartContiner {
height: 100%;
visibility: visible;
opacity: 1;
transition: all .2s;

&--Hidden {
visibility: hidden;
opacity: 0;
transition-delay: 0s;
}
}
}

.TabsChart .TimeframeSelector {
&__Button {

}

@media screen and (max-width: 555px) {
&__Button {
top: 10px;
right: 10px;
z-index: 11;

&--Active {
display: none;
}
}
}
}
43 changes: 43 additions & 0 deletions packages/frontend/src/app/validator/[hash]/TimeframeSelector.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@use '../../../styles/mixins.scss';
@import '../../../styles/variables.scss';

.TimeframeSelector {
&--MenuActive & {
&__Menu {
visibility: visible;
opacity: 1;
transition-delay: .2s;
}
}

&__Menu {
padding: 0 12px !important;
top: 12px;
position: absolute;
z-index: 10;
width: 100%;
// height: 100%;
height: max-content;
left: 0;
backdrop-filter: $blockBackgroundBlur;
visibility: hidden;
opacity: 0;
transition: all .2s;
transition-delay: 0s;
}

&__Button {
position: absolute !important;
top: -36px;
right: 10px;
transition: all .2s;
visibility: visible;
opacity: 1;
height: 28px !important;

&--Active {
background-color: #fff !important;
color: $color-brand-normal !important;
}
}
}
Loading

0 comments on commit f6a8209

Please sign in to comment.