From abaabedfe24c93694acd808b3f7249f65d894e33 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 25 Aug 2023 16:04:16 +0700 Subject: [PATCH 01/10] add sort for ticket pages --- public/locales/en/translation.json | 28 +++ src/components/Ticket/Signatures.tsx | 226 +++++++++++-------- src/hooks/useTicketsType.ts | 3 +- src/pages/TicketsType/TicketList.tsx | 48 +++- src/pages/TicketsType/TicketsType.helpers.ts | 19 ++ src/pages/TicketsType/TicketsType.styles.ts | 10 +- src/pages/TicketsType/TicketsType.tsx | 11 +- 7 files changed, 240 insertions(+), 105 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 25297104..f28b3c5e 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1029,6 +1029,10 @@ "signature3": { "message": "Registering Supernode #3 - Signature:", "description": "Used for the signatures component" + }, + "registeringSupernode": { + "message": "Registering Supernode", + "description": "Used for the signatures component" } }, "transferTicket": { @@ -2862,6 +2866,30 @@ "senseAndNFTCollectionTickets": { "message": "Sense and NFT Collection Tickets", "description": "Used for the Tickets page" + }, + "sortingBy": { + "message": "Sorting by:", + "description": "Used for the Tickets page" + }, + "timestamp": { + "message": "Timestamp", + "description": "Used for the Tickets page" + }, + "blockNumber": { + "message": "Block Height of the TXID", + "description": "Used for the Tickets page" + }, + "blockNumberRegistered": { + "message": "Block Height When Ticket Registered", + "description": "Used for the Tickets page" + }, + "totalCost": { + "message": "Total Cost", + "description": "Used for the Tickets page" + }, + "registeringSupernode": { + "message": "Registering Supernode", + "description": "Used for the Tickets page" } }, "burned": { diff --git a/src/components/Ticket/Signatures.tsx b/src/components/Ticket/Signatures.tsx index 5032df64..65bb955b 100644 --- a/src/components/Ticket/Signatures.tsx +++ b/src/components/Ticket/Signatures.tsx @@ -1,6 +1,10 @@ +import { useState } from 'react'; import Grid from '@material-ui/core/Grid'; import Box from '@material-ui/core/Box'; import parse from 'html-react-parser'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import { ExpandMore as ExpandMoreIcon } from '@material-ui/icons'; import { ISignature } from '@utils/types/ITransactions'; import { translate } from '@utils/helpers/i18n'; @@ -13,6 +17,8 @@ interface ISignaturesProps { } const Signatures: React.FC = ({ signatures, signature, variant }) => { + const [isExpanded, setIsExpanded] = useState(false); + if (signature) { if (variant === 'transaction') { return ( @@ -45,100 +51,132 @@ const Signatures: React.FC = ({ signatures, signature, variant if (signatures) { return ( - - - - {parse(translate('components.ticket.signatures.pastelIDOfUserSubmittingTicket'))} - - - - {Object.keys(signatures.principal)[0]} - - - - - - {parse(translate('components.ticket.signatures.signatureOfUser'))} - - - - - {Object.values(signatures.principal)[0]} - - - - - - - {parse(translate('components.ticket.signatures.supernode1'))} - - - - - {Object.keys(signatures.mn1)[0]} - - - - - - - {parse(translate('components.ticket.signatures.signature1'))} - - - - - {Object.values(signatures.mn1)[0]} - - - - - - - {parse(translate('components.ticket.signatures.supernode2'))} - - - - - {Object.keys(signatures.mn2)[0]} - - - - - - - {parse(translate('components.ticket.signatures.signature2'))} - - - - - {Object.values(signatures.mn2)[0]} - - - - - - - {parse(translate('components.ticket.signatures.supernode3'))} - - - - - {Object.keys(signatures.mn3)[0]} - - - - - - - {parse(translate('components.ticket.signatures.signature3'))} - - - - - {Object.values(signatures.mn3)[0]} - - - + setIsExpanded(isPanelExpanded)} + > + + + + + {parse(translate('components.ticket.signatures.registeringSupernode'))}: + + + + + {isExpanded + ? parse(translate('components.ticket.actionRegistrationTicket.hideDetail')) + : parse( + translate('components.ticket.actionRegistrationTicket.clickToSeeDetail'), + )}{' '} + + + + + + + + + + + {parse( + translate('components.ticket.signatures.pastelIDOfUserSubmittingTicket'), + )} + + + + + {Object.keys(signatures.principal)[0]} + + + + + + + {parse(translate('components.ticket.signatures.signatureOfUser'))} + + + + + {Object.values(signatures.principal)[0]} + + + + + + + {parse(translate('components.ticket.signatures.supernode1'))} + + + + + {Object.keys(signatures.mn1)[0]} + + + + + + + {parse(translate('components.ticket.signatures.signature1'))} + + + + + {Object.values(signatures.mn1)[0]} + + + + + + + {parse(translate('components.ticket.signatures.supernode2'))} + + + + + {Object.keys(signatures.mn2)[0]} + + + + + + + {parse(translate('components.ticket.signatures.signature2'))} + + + + + {Object.values(signatures.mn2)[0]} + + + + + + + {parse(translate('components.ticket.signatures.supernode3'))} + + + + + {Object.keys(signatures.mn3)[0]} + + + + + + + {parse(translate('components.ticket.signatures.signature3'))} + + + + + {Object.values(signatures.mn3)[0]} + + + + + + ); } diff --git a/src/hooks/useTicketsType.ts b/src/hooks/useTicketsType.ts index 55f44491..ac83b691 100644 --- a/src/hooks/useTicketsType.ts +++ b/src/hooks/useTicketsType.ts @@ -15,6 +15,7 @@ export default function useTicketsType( endDate: number | null; }, offset: number, + sort: string, ) { let qStatus = ''; if (status) { @@ -35,7 +36,7 @@ export default function useTicketsType( total: number; senses: TSenseRequests[]; }>( - `${URLS.GET_TICKETS}/${type}?offset=${offset}&limit=${limit}&type=${type}${dateParam}${qStatus}&include=all`, + `${URLS.GET_TICKETS}/${type}?offset=${offset}&limit=${limit}&sort=${sort}&type=${type}${dateParam}${qStatus}&include=all`, axiosGet, SWR_OPTIONS, ); diff --git a/src/pages/TicketsType/TicketList.tsx b/src/pages/TicketsType/TicketList.tsx index 7e4c614c..dd03c561 100644 --- a/src/pages/TicketsType/TicketList.tsx +++ b/src/pages/TicketsType/TicketList.tsx @@ -60,7 +60,11 @@ import { getFileIcon } from '@pages/Details/CascadeDetails/CascadeDetails.helper import CopyButton from '@components/CopyButton/CopyButton'; import noImagePlaceholder from '@assets/images/no-image-placeholder.svg'; -import { TICKET_TYPE_OPTIONS, TICKET_STATUS_OPTIONS } from './TicketsType.helpers'; +import { + TICKET_TYPE_OPTIONS, + TICKET_STATUS_OPTIONS, + TICKET_SORT_OPTIONS, +} from './TicketsType.helpers'; const useStyles = makeStyles((theme: TAppTheme) => { return { @@ -91,7 +95,9 @@ const useStyles = makeStyles((theme: TAppTheme) => { interface ITicketsList { data: ITicket[]; ticketType: string; + ticketSort: string; onTicketTypeChange: (_value: string) => void; + onTicketSortChange: (_value: string) => void; totalTickets: number; isLoading?: boolean; senses?: TSenseRequests[]; @@ -119,6 +125,8 @@ const TicketsList: React.FC = ({ selectedStatus, onDateRangeApply, defaultDateRange, + ticketSort, + onTicketSortChange, }) => { const decodeApiTicket = (apiTicket: string) => { let result = null; @@ -361,6 +369,14 @@ const TicketsList: React.FC = ({ onStatusChange(event.target.value as string); }; + const handleSortChange = ( + event: React.ChangeEvent<{ + value: unknown; + }>, + ) => { + onTicketSortChange(event.target.value as string); + }; + const getStatusOptions = () => { return TICKET_STATUS_OPTIONS.map(option => ({ ...option, @@ -368,6 +384,13 @@ const TicketsList: React.FC = ({ })); }; + const getSortOptions = () => { + return TICKET_SORT_OPTIONS.map(option => ({ + ...option, + name: translateDropdown(option.name), + })); + }; + return ( @@ -400,13 +423,22 @@ const TicketsList: React.FC = ({ classNameWrapper="dropdown-ticket-type" /> {['sense', 'cascade'].includes(ticketType) ? ( - + <> + + + ) : null}
{blocksPeriodFilters.map(({ name, value }) => ( diff --git a/src/pages/TicketsType/TicketsType.helpers.ts b/src/pages/TicketsType/TicketsType.helpers.ts index 8cfb75a4..4986619c 100644 --- a/src/pages/TicketsType/TicketsType.helpers.ts +++ b/src/pages/TicketsType/TicketsType.helpers.ts @@ -67,3 +67,22 @@ export const TICKET_STATUS_OPTIONS = [ value: 'inactivated', }, ]; + +export const TICKET_SORT_OPTIONS = [ + { + name: 'pages.ticketsType.timestamp', + value: 'transactionTime', + }, + { + name: 'pages.ticketsType.blockNumberRegistered', + value: 'blockHeightRegistered', + }, + { + name: 'pages.ticketsType.blockNumber', + value: 'height', + }, + { + name: 'pages.ticketsType.totalCost', + value: 'totalCost', + }, +]; diff --git a/src/pages/TicketsType/TicketsType.styles.ts b/src/pages/TicketsType/TicketsType.styles.ts index 9242c5b6..9e55a5ea 100644 --- a/src/pages/TicketsType/TicketsType.styles.ts +++ b/src/pages/TicketsType/TicketsType.styles.ts @@ -17,6 +17,12 @@ export const TicketsContainer = styled.div` } } + .dropdown-sort { + .MuiInputBase-root { + width: 130px; + } + } + .nowrap { white-space: nowrap; } @@ -26,7 +32,8 @@ export const TicketsContainer = styled.div` border: 1px solid ${props => props.theme.filter.border}; } - .dropdown-status { + .dropdown-status, + .dropdown-sort { margin-left: 10px; } @@ -60,6 +67,7 @@ export const TicketsContainer = styled.div` .dropdown-ticket-type, .dropdown-status, + .dropdown-sort, .list-filter { margin-top: 10px; } diff --git a/src/pages/TicketsType/TicketsType.tsx b/src/pages/TicketsType/TicketsType.tsx index 41613c55..f3a08b86 100644 --- a/src/pages/TicketsType/TicketsType.tsx +++ b/src/pages/TicketsType/TicketsType.tsx @@ -10,7 +10,7 @@ import { blocksPeriodFilters } from '@utils/constants/filter'; import * as TransactionStyles from '@pages/Details/TransactionDetails/TransactionDetails.styles'; import TicketsList from './TicketList'; -import { TICKET_STATUS_OPTIONS } from './TicketsType.helpers'; +import { TICKET_STATUS_OPTIONS, TICKET_SORT_OPTIONS } from './TicketsType.helpers'; import * as Styles from './TicketsType.styles'; interface ParamTypes { @@ -22,6 +22,7 @@ const LIMIT = 6; const TicketsType: React.FC = () => { const { type } = useParams(); const [selectedType, setTicketType] = useState(type); + const [selectedSort, setTicketSort] = useState(TICKET_SORT_OPTIONS[0].value); const [selectedStatus, setSelectedStatus] = useState(TICKET_STATUS_OPTIONS[0].value); const [selectedTime, setSelectedTime] = useState(blocksPeriodFilters[4].value); const [currentPage, setCurrentPage] = useState(0); @@ -39,6 +40,7 @@ const TicketsType: React.FC = () => { selectedStatus, customDateRange, currentPage * LIMIT, + selectedSort, ); const handleTicketTypeChange = (val: string) => { @@ -46,6 +48,11 @@ const TicketsType: React.FC = () => { setCurrentPage(0); }; + const handleTicketSortChange = (val: string) => { + setTicketSort(val); + setCurrentPage(0); + }; + useEffect(() => { (async () => { setTicketType(type); @@ -92,7 +99,9 @@ const TicketsType: React.FC = () => { Date: Thu, 21 Sep 2023 13:34:15 +0700 Subject: [PATCH 02/10] add live update for block list --- src/pages/Blocks/Blocks.tsx | 5 +++++ .../Statistics/BlockStatistics/BlockStatistics.helpers.ts | 4 +++- src/pages/Statistics/BlockStatistics/BlockStatistics.tsx | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pages/Blocks/Blocks.tsx b/src/pages/Blocks/Blocks.tsx index 4abe4a1f..637e3a75 100644 --- a/src/pages/Blocks/Blocks.tsx +++ b/src/pages/Blocks/Blocks.tsx @@ -103,6 +103,11 @@ const Blocks = () => { } }, [filter.dateRange, filter.dropdownType, filter.customDateRange]); + useEffect(() => { + setParams({ ...apiParams }); + swrSetSize(1); + }, [blockElements, blocksUnconfirmed]); + const getMovementTransactionsTitle = () => ( {parse(translate('pages.blocks.blockList'))}{' '} diff --git a/src/pages/Statistics/BlockStatistics/BlockStatistics.helpers.ts b/src/pages/Statistics/BlockStatistics/BlockStatistics.helpers.ts index 62bdab0e..4bd84c19 100644 --- a/src/pages/Statistics/BlockStatistics/BlockStatistics.helpers.ts +++ b/src/pages/Statistics/BlockStatistics/BlockStatistics.helpers.ts @@ -33,7 +33,9 @@ export const transformBlocksData = ( ticketsCount: totalTickets > 1 ? translateDropdown('pages.statistics.tickets', { ticketsCount: totalTickets }) - : translateDropdown('pages.statistics.ticket', { ticketsCount: totalTickets || 0 }), + : translateDropdown('pages.statistics.ticket', { + ticketsCount: totalTickets >= 0 ? totalTickets : 0, + }), status: 'entered', }; }); diff --git a/src/pages/Statistics/BlockStatistics/BlockStatistics.tsx b/src/pages/Statistics/BlockStatistics/BlockStatistics.tsx index 6908896e..24e65b18 100644 --- a/src/pages/Statistics/BlockStatistics/BlockStatistics.tsx +++ b/src/pages/Statistics/BlockStatistics/BlockStatistics.tsx @@ -161,6 +161,9 @@ const StatisticsBlocks: React.FC = ({ blockElements, blocksUn ); }; + const start = blocksUnconfirmed?.length ? 1 : 0; + const end = blocksUnconfirmed?.length ? 8 : 7; + return ( <> @@ -190,7 +193,7 @@ const StatisticsBlocks: React.FC = ({ blockElements, blocksUn {layout.items - .slice(1, 8) + .slice(start, end) .map( ({ id, height, size, transactionCount, minutesAgo, ticketsCount, status }) => (
From 772ded51d3e9193f23251a3d7c521bf602584caa Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Mon, 16 Oct 2023 15:18:52 +0700 Subject: [PATCH 03/10] add sort for Top-10 Most Similar Registered Images on Pastel When Submitted section --- .../SenseDetails/SenseDetails.styles.ts | 4 + .../SenseDetails/SimilarRegisteredImages.tsx | 101 ++++++++++++++---- 2 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/pages/Details/SenseDetails/SenseDetails.styles.ts b/src/pages/Details/SenseDetails/SenseDetails.styles.ts index 2955d6ff..8f66b180 100644 --- a/src/pages/Details/SenseDetails/SenseDetails.styles.ts +++ b/src/pages/Details/SenseDetails/SenseDetails.styles.ts @@ -519,6 +519,10 @@ export const TableWrapper = styled.div` max-width: 100%; overflow-x: auto; + .MuiTableSortLabel-icon { + display: none; + } + .table__row-header { th { white-space: nowrap; diff --git a/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx b/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx index f94f8849..21946702 100644 --- a/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx +++ b/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx @@ -1,13 +1,17 @@ +import { useState } from 'react'; import { withStyles } from '@material-ui/core/styles'; import Table from '@material-ui/core/Table'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; import TableContainer from '@material-ui/core/TableContainer'; +import TableSortLabel from '@material-ui/core/TableSortLabel'; import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; import Paper from '@material-ui/core/Paper'; import Tooltip from '@material-ui/core/Tooltip'; import InfoIcon from '@material-ui/icons/Info'; +import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; +import ArrowDropUp from '@material-ui/icons/ArrowDropUp'; import parse from 'html-react-parser'; import { TAppTheme } from '@theme/index'; @@ -64,7 +68,8 @@ const formatImageHash = (hash: string) => { }; type TSimilarRegisteredImage = { - image: string | null; + rank: number; + image?: string; imageHash: string; imageHashOriginal: string; dateTimeAdded: string; @@ -87,7 +92,7 @@ export const getSimilarRegisteredImagesData = (rarenessScoresTable: string) => { const getRegisterTime = (value: string | Array) => { try { - if (value?.length) { + if (Array.isArray(value)) { return value[0][0]; } return value?.toString()?.split('.')[0]; @@ -98,9 +103,10 @@ export const getSimilarRegisteredImagesData = (rarenessScoresTable: string) => { let fancyGridData = []; for (let i = 0; i < Object.values(uncompressedRarenessScoresTable.image_hash).length; i += 1) { fancyGridData.push({ + rank: i + 1, image: uncompressedRarenessScoresTable.thumbnail[i] ? `data:image/jpeg;base64,${uncompressedRarenessScoresTable.thumbnail[i]}` - : null, + : '', imageHash: formatImageHash(uncompressedRarenessScoresTable.image_hash[i]), imageHashOriginal: uncompressedRarenessScoresTable.image_hash[i], dateTimeAdded: getRegisterTime(uncompressedRarenessScoresTable.register_time[i]), @@ -161,7 +167,7 @@ const SimilarRegisteredImageRow: React.FC = ({ }} > - {index + 1} + {item.rank} = ({ ); }; +type Order = 'asc' | 'desc'; + +function descendingComparator(a: T, b: T, orderBy: keyof T) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + const SimilarRegisteredImages: React.FC = ({ rarenessScoresTable }) => { + const [order, setOrder] = useState('asc'); + const [orderBy, setOrderBy] = useState('rank'); + if (!rarenessScoresTable) { return ( @@ -243,6 +264,31 @@ const SimilarRegisteredImages: React.FC = ({ rarenessS } const fancyGridData = getSimilarRegisteredImagesData(rarenessScoresTable); + const handleRequestSort = (property: keyof TSimilarRegisteredImage) => () => { + const isAsc = (orderBy === property && order === 'asc') || orderBy !== property; + setOrder(isAsc ? 'desc' : 'asc'); + setOrderBy(property); + }; + + const renderHeaderItem = (field: keyof TSimilarRegisteredImage, langField: string) => { + const renderSortIcon = () => { + if (orderBy === field) { + return order === 'desc' ? : ; + } + return null; + }; + + return ( + + {parse(translate(`pages.senseDetails.${langField}`))} {renderSortIcon()} + + ); + }; + return ( @@ -250,55 +296,64 @@ const SimilarRegisteredImages: React.FC = ({ rarenessS - {parse(translate('pages.senseDetails.rank'))} + {renderHeaderItem('rank', 'rank')} {parse(translate('pages.senseDetails.thumbnail'))} - {parse(translate('pages.senseDetails.imageHash'))} + {renderHeaderItem('imageHash', 'imageHash')} - {parse(translate('pages.senseDetails.dateTimeAdded'))} + {renderHeaderItem('dateTimeAdded', 'dateTimeAdded')} - {parse(translate('pages.senseDetails.matchType'))} + {renderHeaderItem('matchType', 'matchType')} - {parse(translate('pages.senseDetails.dupeProbability'))} + {renderHeaderItem('finalDupeProbability', 'dupeProbability')} {parse(translate('pages.senseDetails.dupeProbability'))} - {parse(translate('pages.senseDetails.cosineSimilarity'))} + {renderHeaderItem('cosineSimilarity', 'cosineSimilarity')} - {parse(translate('pages.senseDetails.cosineGain'))} + {renderHeaderItem('cosineGain', 'cosineGain')} - {parse(translate('pages.senseDetails.hoeffdingsDependency'))} + {renderHeaderItem('hoeffdingDependency', 'hoeffdingsDependency')} - {parse(translate('pages.senseDetails.hoeffdingGain'))} + {renderHeaderItem('hoeffdingGain', 'hoeffdingGain')} - {parse(translate('pages.senseDetails.hilbertSchmidtInformationCriteria'))} + {renderHeaderItem( + 'hilbertSchmidtInformationCriteria', + 'hilbertSchmidtInformationCriteria', + )} - {parse(translate('pages.senseDetails.hilbertSchmidtGain'))} + {renderHeaderItem('hilbertSchmidtGain', 'hilbertSchmidtGain')} - {fancyGridData?.map((item, index) => ( - - ))} + {fancyGridData + ?.sort((a, b) => + order === 'desc' + ? descendingComparator(a, b, orderBy) + : -descendingComparator(a, b, orderBy), + ) + ?.map((item, index) => ( + + ))} {!fancyGridData.length ? ( From 61d396fa6de4db66f8e40229690d6b806492345f Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Tue, 7 Nov 2023 15:17:58 +0700 Subject: [PATCH 04/10] update UI for TransferTicket and Network (kB/s) chart section in homepage --- public/locales/en/translation.json | 8 +++++++ src/components/Summary/Summary.tsx | 10 ++++---- src/components/Ticket/TransferTicket.tsx | 23 ++++++++++++++++++- .../Details/CascadeDetails/Transfers.tsx | 8 +++---- .../TransactionDetails.styles.ts | 4 ++++ .../TransactionDetails/TransactionDetails.tsx | 2 +- src/utils/helpers/statisticsLib.ts | 4 ++-- 7 files changed, 47 insertions(+), 12 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index f28b3c5e..c8ef9bbf 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1067,6 +1067,14 @@ "timestamp": { "message": "Timestamp:", "description": "Used for the TransferTicket component" + }, + "activationTxID": { + "message": "Activation txID:", + "description": "Used for the TransferTicket component" + }, + "ticketDetail": { + "message": "Ticket detail", + "description": "Used for the TransferTicket component" } }, "userNameChangeTicket": { diff --git a/src/components/Summary/Summary.tsx b/src/components/Summary/Summary.tsx index 7853628c..0d4818f6 100644 --- a/src/components/Summary/Summary.tsx +++ b/src/components/Summary/Summary.tsx @@ -319,7 +319,9 @@ const Summary: React.FC = () => { } if (sumKey === 'gigaHashPerSec') { - return formatNumber(Number(value) * NETWORK_RANGE, { decimalsLength: 2 }); + return formatNumber(Number(value.toString().replaceAll(',', '')) * NETWORK_RANGE, { + decimalsLength: 2, + }); } return value; @@ -351,7 +353,7 @@ const Summary: React.FC = () => { color="textSecondary" noWrap percentagecolor={`${ - difference > 0 + Number(difference) > 0 ? themeVariant.custom.green.success : themeVariant.custom.red.error }`} @@ -361,9 +363,9 @@ const Summary: React.FC = () => { : parse(translate('components.summary.last24h'))}
- {`${difference > 0 ? '+' : ''}`} + {`${Number(difference) > 0 ? '+' : ''}`} {difference}%  - {difference > 0 ? ( + {Number(difference) > 0 ? ( = ({ ticket, variant }) => /> ); }; + const getOfferType = () => { switch (ticket.otherData.offerType) { case 'sense': + case 'sense-offer': return parse(translate('components.ticket.offerTicket.sense')); case 'cascade': return parse(translate('components.ticket.offerTicket.cascade')); @@ -73,6 +75,18 @@ const TransferTicket: React.FC = ({ ticket, variant }) => } }; + const itemUrl = () => { + switch (ticket.otherData.offerType) { + case 'sense': + case 'sense-offer': + return `/sense?txid=${ticket.otherData.regTxId}`; + case 'cascade': + return `/cascade?txid=${ticket.otherData.regTxId}`; + default: + return `/nft?txid=${ticket.otherData.regTxId}`; + } + }; + return ( @@ -128,7 +142,7 @@ const TransferTicket: React.FC = ({ ticket, variant }) => - {parse(translate('components.ticket.transferTicket.itemTxId'))} + {parse(translate('components.ticket.transferTicket.activationTxID'))} @@ -157,7 +171,14 @@ const TransferTicket: React.FC = ({ ticket, variant }) => value={ticket.offer_txid} title={ticket.offer_txid} className="address-link" + />{' '} + ( + + ) diff --git a/src/pages/Details/CascadeDetails/Transfers.tsx b/src/pages/Details/CascadeDetails/Transfers.tsx index b4f104a7..02ba39e0 100644 --- a/src/pages/Details/CascadeDetails/Transfers.tsx +++ b/src/pages/Details/CascadeDetails/Transfers.tsx @@ -102,7 +102,7 @@ const Transfers = () => {
{
{
{
{ )} {tickets.length ? ( - + Date: Thu, 9 Nov 2023 12:06:07 +0700 Subject: [PATCH 05/10] add a button to allow user to redirect to homepage on the error screen --- src/pages/ErrorHandler/ErrorHandler.styles.ts | 23 +++++++++++++++- src/pages/ErrorHandler/ErrorHandler.tsx | 27 ++++++++++++------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/pages/ErrorHandler/ErrorHandler.styles.ts b/src/pages/ErrorHandler/ErrorHandler.styles.ts index 5575c408..8cb83c4c 100644 --- a/src/pages/ErrorHandler/ErrorHandler.styles.ts +++ b/src/pages/ErrorHandler/ErrorHandler.styles.ts @@ -1,6 +1,6 @@ import styled from 'styled-components/macro'; import { spacing } from '@material-ui/system'; -import { Button as MuiButton } from '@material-ui/core'; +import { Button as MuiButton, Box as MuiBox } from '@material-ui/core'; import { MuiButtonSpacingType } from '@utils/types/styles'; @@ -31,3 +31,24 @@ export const ContentWrapper = styled.div` margin: auto; } `; + +export const Box = styled(MuiBox)` + display: flex; + align-item: center; + justify-content: center; + + .MuiButtonBase-root:last-child { + margin-left: 8px; + } + + ${props => props.theme.breakpoints.down(425)} { + flex-direction: column; + max-width: 250px; + margin: auto; + + .MuiButtonBase-root:last-child { + margin-left: 0; + margin-top: 8px; + } + } +`; diff --git a/src/pages/ErrorHandler/ErrorHandler.tsx b/src/pages/ErrorHandler/ErrorHandler.tsx index 0c35da9b..107335f8 100644 --- a/src/pages/ErrorHandler/ErrorHandler.tsx +++ b/src/pages/ErrorHandler/ErrorHandler.tsx @@ -54,15 +54,24 @@ class ErrorHandler extends React.Component {t('pages.errorHandler.refresh.message')} - - window.location.reload()} - variant="contained" - color="secondary" - mt={2} - > - {t('pages.errorHandler.btnRefresh.message')} - + + window.location.reload()} + variant="contained" + color="secondary" + > + {t('pages.errorHandler.btnRefresh.message')} + + { + window.location.href = '/'; + }} + variant="contained" + color="secondary" + > + {t('pages.404.backToHomepage.message')} + +
From 633cf5192484b99d774ad40e908b4179599b5118 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 10 Nov 2023 15:54:24 +0700 Subject: [PATCH 06/10] create a new chart that tracks the aggregate growth of PSL Burnt over time --- public/locales/en/translation.json | 12 ++ src/hooks/usePslBurnt.ts | 16 +++ .../PSLBurnt/__test__/PSLBurnt.test.tsx | 45 +++++++ .../HistoricalStatistics/PSLBurnt/index.tsx | 82 ++++++++++++ src/routes/index.tsx | 11 ++ src/utils/constants/routes.ts | 1 + src/utils/constants/statistics.ts | 7 + src/utils/helpers/chartOptions.ts | 120 +++++++++++++++++- 8 files changed, 287 insertions(+), 7 deletions(-) create mode 100644 src/hooks/usePslBurnt.ts create mode 100644 src/pages/HistoricalStatistics/PSLBurnt/__test__/PSLBurnt.test.tsx create mode 100644 src/pages/HistoricalStatistics/PSLBurnt/index.tsx diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index c8ef9bbf..cb3dc10a 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -2268,6 +2268,10 @@ "feeSchedule": { "message": "Fee Schedule", "description": "Used for the HistoricalStatistics page" + }, + "pslBurnt": { + "message": "{{currency}} Burnt", + "description": "Used for the HistoricalStatistics page" } }, "movement": { @@ -3703,6 +3707,10 @@ "totalFingerprints": { "message": "Total fingerprints", "description": "Used for the chartOptions" + }, + "pslBurnt": { + "message": "{{currency}} Burnt", + "description": "Used for the chartOptions" } }, "constants": { @@ -3904,6 +3912,10 @@ "feeSchedule": { "message": "Fee Schedule", "description": "Used for the constants" + }, + "pslBurnt": { + "message": "{{currency}} Burnt", + "description": "Used for the constants" } } } diff --git a/src/hooks/usePslBurnt.ts b/src/hooks/usePslBurnt.ts new file mode 100644 index 00000000..51e472b6 --- /dev/null +++ b/src/hooks/usePslBurnt.ts @@ -0,0 +1,16 @@ +import useSWRInfinite from 'swr/infinite'; + +import { axiosGet } from '@utils/helpers/useFetch/useFetch'; +import * as URLS from '@utils/constants/urls'; +import { TFeeSchedule } from '@utils/types/IStatistics'; + +export default function usePslBurnt(period: string) { + const { data, isLoading } = useSWRInfinite<{ data: Array }>( + () => `${URLS.GET_TOTAL_BURNED}?period=${period}`, + axiosGet, + ); + return { + data: data ? data[0].data : null, + isLoading, + }; +} diff --git a/src/pages/HistoricalStatistics/PSLBurnt/__test__/PSLBurnt.test.tsx b/src/pages/HistoricalStatistics/PSLBurnt/__test__/PSLBurnt.test.tsx new file mode 100644 index 00000000..483e02ff --- /dev/null +++ b/src/pages/HistoricalStatistics/PSLBurnt/__test__/PSLBurnt.test.tsx @@ -0,0 +1,45 @@ +import { shallow } from 'enzyme'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import 'jest-styled-components'; + +import i18next from '../../../../utils/helpers/i18n'; +import PSLBurnt from '../index'; + +jest.mock('i18next-http-backend'); +jest.mock('react-i18next', () => ({ + useTranslation: () => { + return { + t: (str: string) => str, + i18n: { + changeLanguage: () => + new Promise(() => { + // noop + }), + }, + }; + }, + initReactI18next: { + type: '3rdParty', + init: () => { + // noop + }, + }, +})); +i18next.t = jest.fn().mockImplementation((...arg) => { + return arg[0]; +}); +const mockStore = configureMockStore(); +const store = mockStore({}); + +describe('pages/HistoricalStatistics/PSLBurnt', () => { + const wrapper = shallow( + + + , + ); + + test('renders correctly', () => { + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/src/pages/HistoricalStatistics/PSLBurnt/index.tsx b/src/pages/HistoricalStatistics/PSLBurnt/index.tsx new file mode 100644 index 00000000..d6d6a608 --- /dev/null +++ b/src/pages/HistoricalStatistics/PSLBurnt/index.tsx @@ -0,0 +1,82 @@ +import { useEffect, useState } from 'react'; +import parse from 'html-react-parser'; + +import { PeriodTypes, transformFeeSchedule } from '@utils/helpers/statisticsLib'; +import { periods, info, cacheList } from '@utils/constants/statistics'; +import { useBackgroundChart } from '@utils/hooks'; +import { readCacheValue, setCacheValue } from '@utils/helpers/localStorage'; +import { TLineChartData } from '@utils/types/IStatistics'; +import HistoricalStatisticsLayout from '@components/HistoricalStatisticsLayout/HistoricalStatisticsLayout'; +import { getCurrencyName } from '@utils/appInfo'; +import usePslBurnt from '@hooks/usePslBurnt'; +import { translate } from '@utils/helpers/i18n'; + +import { EChartsLineChart } from '../Chart/EChartsLineChart'; + +function PSLBurnt() { + const [chartData, setChartData] = useState(null); + const [currentBgColor, handleBgColorChange] = useBackgroundChart(); + const [period, setPeriod] = useState(periods[1][0]); + const [isLoading, setLoading] = useState(false); + const swrData = usePslBurnt(period); + + useEffect(() => { + let currentCache = readCacheValue(cacheList.totalSupply) || {}; + if (currentCache[period]) { + setChartData(currentCache[period].parseData as TLineChartData); + setLoading(false); + } else { + setLoading(true); + } + if (!swrData.isLoading && swrData.data) { + const parseData = transformFeeSchedule(swrData.data, period, ''); + setChartData(parseData); + currentCache = { + ...currentCache, + [period]: { + parseData, + }, + }; + setCacheValue( + cacheList.totalSupply, + JSON.stringify({ + currentCache, + lastDate: Date.now(), + }), + ); + setLoading(false); + } + }, [period, swrData.isLoading, swrData.data]); + + const handlePeriodFilterChange = (value: PeriodTypes) => { + setPeriod(value); + }; + + return ( + + + + ); +} + +export default PSLBurnt; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 186204b8..b621b00b 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -71,6 +71,7 @@ const CollectionDetails = loadable( const CascadeDetails = loadable(() => import('@pages/Details/CascadeDetails/CascadeDetails')); const NftDetails = loadable(() => import('@pages/Details/NftDetails/NftDetails')); const FeeSchedule = loadable(() => import('@pages/HistoricalStatistics/FeeSchedule')); +const PSLBurnt = loadable(() => import('@pages/HistoricalStatistics/PSLBurnt')); const explorerRoutes = { id: 'routes.explorer', @@ -407,6 +408,15 @@ const feeScheduleStatisticsRoutes = { children: null, }; +const pslBurntStatisticsRoutes = { + id: 'pslBurnt', + path: ROUTES.STATISTICS_PSL_BURNT, + component: PSLBurnt, + icon: null, + seoTitle: 'routes.pslBurnt', + children: null, +}; + const senseDetailsRoutes = { id: 'routes.senseDetails', path: ROUTES.SENSE_DETAILS, @@ -520,6 +530,7 @@ export const pageRoutes = [ cascadeDetailsRoutes, nftDetailsRoutes, feeScheduleStatisticsRoutes, + pslBurntStatisticsRoutes, ]; export const sidebarRoutes = [ diff --git a/src/utils/constants/routes.ts b/src/utils/constants/routes.ts index a468e1df..9d7bfc10 100644 --- a/src/utils/constants/routes.ts +++ b/src/utils/constants/routes.ts @@ -36,6 +36,7 @@ export const STATISTICS_TOTAL_SUPPLY = `${STATISTICS_OVERTIME}/total-supply`; export const STATISTICS_PERCENT_OF_PSL_STAKED = `${STATISTICS_OVERTIME}/percent-of-psl-staked`; export const STATISTICS_ACCOUNTS = `${STATISTICS_OVERTIME}/accounts`; export const STATISTICS_FEE_SCHEDULE = `${STATISTICS_OVERTIME}/fee-schedule`; +export const STATISTICS_PSL_BURNT = `${STATISTICS_OVERTIME}/psl-burnt`; export const CASCADE_AND_SENSE_STATISTICS = '/cascade-and-sense-statistics'; export const SENSE_DETAILS = '/sense'; export const PASTEL_ID_DETAILS = '/pastelid'; diff --git a/src/utils/constants/statistics.ts b/src/utils/constants/statistics.ts index 9fc4f08b..6a663a7a 100644 --- a/src/utils/constants/statistics.ts +++ b/src/utils/constants/statistics.ts @@ -157,6 +157,12 @@ export const statistics = [ url: routes.STATISTICS_FEE_SCHEDULE, image: generatePreviewUrl(routes.STATISTICS_FEE_SCHEDULE), }, + { + id: 'pslBurnt', + title: 'constants.statistics.pslBurnt', + url: routes.STATISTICS_PSL_BURNT, + image: generatePreviewUrl(routes.STATISTICS_PSL_BURNT), + }, ]; export const themes = [ @@ -203,6 +209,7 @@ export const csvHeaders: TCsvHeaderType = { circulatingSupply: commonCsvFields, totalSupply: commonCsvFields, percentOfPSLStaked: commonCsvFields, + pslBurnt: commonCsvFields, networktotals: [ { label: 'constants.statistics.receiveSent', key: 'value' }, { label: 'constants.statistics.createdTimeCSV', key: 'time' }, diff --git a/src/utils/helpers/chartOptions.ts b/src/utils/helpers/chartOptions.ts index 80cd8c1d..57b6d4d3 100644 --- a/src/utils/helpers/chartOptions.ts +++ b/src/utils/helpers/chartOptions.ts @@ -1961,6 +1961,107 @@ export function getThemeInitOption(args: TThemeInitOption): EChartsOption { }, animation: false, }, + pslBurnt: { + backgroundColor: theme?.backgroundColor, + textStyle: { + color: theme?.color, + }, + color: ['#cd6661'], + grid: { + top: 8, + right: 40, + bottom: 70, + left: 60, + show: false, + }, + dataZoom: [ + { + type: 'inside', + start: 0, + end: 100, + }, + { + start: 0, + end: 100, + }, + ], + tooltip: { + trigger: 'axis', + formatter(params: TChartParams[]) { + return ` +
+
${generateTooltipLabel( + new Date(params[0].axisValue), + granularity, + )}
+
${params[0].marker} ${formatNumber(params[0].value, { + decimalsLength: 1, + })} ${getCurrencyName()}
+
+ `; + }, + }, + xAxis: { + type: 'category', + data: dataX, + boundaryGap: false, + axisLabel: { + formatter(value: string, index: number) { + let isShowMinutesFor24h = false; + if (period === '24h' && dataX && (index === 0 || dataX.length - 1 === index)) { + isShowMinutesFor24h = true; + } + if (period && periods[9].indexOf(period) !== -1) { + const date = format(new Date(value), 'MM/dd/yyyy'); + if (firstDay !== date) { + firstDay = date; + return generateXAxisLabel(new Date(value), period, isShowMinutesFor24h); + } + return null; + } + return value ? generateXAxisLabel(new Date(value), period, isShowMinutesFor24h) : null; + }, + showMaxLabel: true, + interval: generateXAxisInterval('1d', period, dataX, width), + }, + }, + yAxis: { + type: 'value', + min: minY, + max: maxY, + interval: (maxY - minY) / 5, + splitLine: { + show: false, + }, + axisLabel: { + formatter(value: string) { + return getYAxisLabel(Number(value), minY, maxY); + }, + }, + axisLine: { + show: true, + }, + }, + series: { + type: 'line', + name: translateDropdown('chartOptions.pslBurnt', { currency: getCurrencyName() }), + data: dataY, + showSymbol: false, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: '#cd6661', + }, + { + offset: 1, + color: theme?.backgroundColor ?? '#F4F4F4', + }, + ]), + }, + }, + animation: false, + }, }; return chartOptions[chartName]; @@ -2116,6 +2217,12 @@ export function getThemeUpdateOption(args: TThemeInitOption): EChartsOption { color: theme?.color, }, }, + pslBurnt: { + backgroundColor: theme?.backgroundColor, + textStyle: { + color: theme?.color, + }, + }, circulatingSupply: { backgroundColor: theme?.backgroundColor, textStyle: { @@ -4176,14 +4283,13 @@ export function getSummaryThemeUpdateOption(args: TThemeInitOption): EChartsOpti splitLine: { show: false, }, - axisLine: { - show: false, - }, - axisTick: { - show: false, - }, axisLabel: { - show: false, + formatter(value: string) { + return getYAxisLabel(Number(value), minY, maxY); + }, + }, + axisLine: { + show: true, }, }, series: { From 8bd00ccca4ce9aa04b4c25c1559164337babaeb2 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Mon, 13 Nov 2023 16:16:06 +0700 Subject: [PATCH 07/10] add snapshots test for PSL Burnt --- .../PSLBurnt/__test__/__snapshots__/PSLBurnt.test.tsx.snap | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/pages/HistoricalStatistics/PSLBurnt/__test__/__snapshots__/PSLBurnt.test.tsx.snap diff --git a/src/pages/HistoricalStatistics/PSLBurnt/__test__/__snapshots__/PSLBurnt.test.tsx.snap b/src/pages/HistoricalStatistics/PSLBurnt/__test__/__snapshots__/PSLBurnt.test.tsx.snap new file mode 100644 index 00000000..705d7c55 --- /dev/null +++ b/src/pages/HistoricalStatistics/PSLBurnt/__test__/__snapshots__/PSLBurnt.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`pages/HistoricalStatistics/PSLBurnt renders correctly 1`] = `ShallowWrapper {}`; From c57618fdf076fcbf0b1a3317fcaf54e7ab0da799 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Mon, 13 Nov 2023 16:38:24 +0700 Subject: [PATCH 08/10] add route lang for PSL Burmt --- public/locales/en/translation.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index cb3dc10a..9630e1e0 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -3553,6 +3553,10 @@ "feeSchedule": { "message": "Fee Schedule", "description": "Used for the routes" + }, + "pslBurnt": { + "message": "{{currency}} Burnt", + "description": "Used for the routes" } }, "chartOptions": { From 056bc0662f6d8b93a04c375d12128cfebedeb814 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 17 Nov 2023 09:31:36 +0700 Subject: [PATCH 09/10] update download csv on address detail page --- public/locales/en/translation.json | 4 ++ .../Details/AddressDetails/AddressDetails.tsx | 64 +++++++++++-------- .../SenseDetails/SimilarRegisteredImages.tsx | 2 +- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 9630e1e0..70e471d3 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1269,6 +1269,10 @@ "message": "Download CSV", "description": "Used for the CascadeAndSenseStatistics page" }, + "downloading": { + "message": "Downloading...", + "description": "Used for the CascadeAndSenseStatistics page" + }, "address": { "message": "{{currency}} Address", "description": "Used for the CascadeAndSenseStatistics page" diff --git a/src/pages/Details/AddressDetails/AddressDetails.tsx b/src/pages/Details/AddressDetails/AddressDetails.tsx index 73df1c55..d38a9473 100644 --- a/src/pages/Details/AddressDetails/AddressDetails.tsx +++ b/src/pages/Details/AddressDetails/AddressDetails.tsx @@ -1,6 +1,5 @@ -import React, { useState, useRef, useEffect } from 'react'; +import { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; -import { CSVLink } from 'react-csv'; import { CircularProgress, Grid } from '@material-ui/core'; import Box from '@material-ui/core/Box'; import Tooltip from '@material-ui/core/Tooltip'; @@ -13,11 +12,12 @@ import InfinityTable, { import { translate, translateDropdown } from '@utils/helpers/i18n'; import { getCurrencyName, isPastelBurnAddress } from '@utils/appInfo'; -import { eChartLineStyles } from '@pages/HistoricalStatistics/Chart/styles'; import * as TableStyles from '@components/Table/Table.styles'; import Fire from '@components/SvgIcon/Fire'; import { useLatestTransactions, useBalanceHistory } from '@hooks/useAddressDetails'; import BurnAddressIcon from '@pages/Details/TransactionDetails/BurnAddressIcon'; +import * as NftDetailsStyles from '@pages/Details/NftDetails/NftDetails.styles'; +import { axiosInstance, getBaseURL } from '@utils/helpers/useFetch/useFetch'; import { DATA_FETCH_LIMIT, @@ -39,30 +39,20 @@ interface IAddressDataRef { } const AddressDetails = () => { - const transactionHistoryCSVHeaders = [ - { label: translateDropdown('pages.addressDetails.hash'), key: 'transactionHash' }, - { - label: translateDropdown('pages.addressDetails.amount', { currency: getCurrencyName() }), - key: 'amount', - }, - { label: translateDropdown('pages.addressDetails.direction'), key: 'direction' }, - { label: translateDropdown('pages.addressDetails.timestamp'), key: 'timestamp' }, - ]; + const [status, setStatus] = useState(''); const { id } = useParams(); const [apiParams, setParams] = useState({ sortBy: ADDRESS_TRANSACTION_TIMESTAMP_KEY, sortDirection: DATA_DEFAULT_SORT, }); - const { addresses, isLoading, swrSize, swrSetSize, csvData } = useLatestTransactions( + const { addresses, isLoading, swrSize, swrSetSize } = useLatestTransactions( id, DATA_FETCH_LIMIT, apiParams.sortBy, apiParams.sortDirection, ); const swrData = useBalanceHistory(id); - const styles = eChartLineStyles(); - const downloadRef = useRef(null); const [isMobile, setMobileView] = useState(false); const handleFetchMoreTransactions = (reachedTableBottom: boolean) => { @@ -100,6 +90,29 @@ const AddressDetails = () => { const isBurnAddress = isPastelBurnAddress(id); + const handleDownloadFile = () => { + const date = new Date(); + const fileName = `Transaction_History__${id}__${date.getFullYear()}_${ + date.getMonth() + 1 + }_${date.getDate()}.csv`; + + setStatus('downloading'); + const url = `${getBaseURL()}/v1/addresses/download-csv/${id}`; + const link = document.createElement('a'); + link.target = '_blank'; + link.download = fileName; + axiosInstance + .get(url, { responseType: 'blob' }) + .then(res => { + link.href = URL.createObjectURL(new Blob([res.data], { type: 'text/csv' })); + link.click(); + setStatus('done'); + }) + .catch(() => { + setStatus('error'); + }); + }; + const generateAddTitle = () => { return ( @@ -118,23 +131,18 @@ const AddressDetails = () => { }; const generateTitle = () => { - const date = new Date(); - const fileName = `Transaction_History__${id}__${date.getFullYear()}_${ - date.getMonth() + 1 - }_${date.getDate()}.csv`; return (

{parse(translate('pages.addressDetails.latestTransactions'))}

- - {parse(translate('pages.addressDetails.downloadCSV'))} - + {status === 'downloading' + ? parse(translate('pages.addressDetails.downloading')) + : parse(translate('pages.addressDetails.downloadCSV'))} +
); }; diff --git a/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx b/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx index 21946702..cb32d1b3 100644 --- a/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx +++ b/src/pages/Details/SenseDetails/SimilarRegisteredImages.tsx @@ -108,7 +108,7 @@ export const getSimilarRegisteredImagesData = (rarenessScoresTable: string) => { ? `data:image/jpeg;base64,${uncompressedRarenessScoresTable.thumbnail[i]}` : '', imageHash: formatImageHash(uncompressedRarenessScoresTable.image_hash[i]), - imageHashOriginal: uncompressedRarenessScoresTable.image_hash[i], + imageHashOriginal: uncompressedRarenessScoresTable.image_hash[i].split('_')[0], dateTimeAdded: getRegisterTime(uncompressedRarenessScoresTable.register_time[i]), likelyDupe: uncompressedRarenessScoresTable.is_likely_dupe[i], matchType: uncompressedRarenessScoresTable.match_type[i], From 58f65ee0ea742a91bd25e5133acf1501c512f9b9 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 17 Nov 2023 09:45:09 +0700 Subject: [PATCH 10/10] fix dublicate image hash on Top-10 Most Similar Registered Images on Pastel When Submitted section --- src/pages/Details/SenseDetails/SenseDetails.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/Details/SenseDetails/SenseDetails.tsx b/src/pages/Details/SenseDetails/SenseDetails.tsx index 08bb3614..a82b100d 100644 --- a/src/pages/Details/SenseDetails/SenseDetails.tsx +++ b/src/pages/Details/SenseDetails/SenseDetails.tsx @@ -419,7 +419,10 @@ const SimilarRegisteredImagesWrapper = ({ sense }: { sense: TSenseRequests }) => }; const SenseDetails: React.FC = () => { - const id = getParameterByName('hash'); + let id = getParameterByName('hash'); + if (id) { + id = id.split('_')[0] as string; + } const txid = getParameterByName('txid'); const matchType = getParameterByName('matchType'); const { senseData: sense, isLoading } = useSenseDetails(id, txid);