From 958304038f6e42cc95064588adf7e711e3da1236 Mon Sep 17 00:00:00 2001 From: pmjanus Date: Sat, 22 Jun 2024 10:44:28 -0400 Subject: [PATCH 1/2] paginate by action --- src/components/TransactionsTable.vue | 108 +++++++++++---------------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/src/components/TransactionsTable.vue b/src/components/TransactionsTable.vue index d83e682c..41cf2b53 100644 --- a/src/components/TransactionsTable.vue +++ b/src/components/TransactionsTable.vue @@ -251,9 +251,8 @@ export default defineComponent({ const filterRows = () => { filteredRows.value = rows.value; }; - const loadTableData = async (): Promise => { - let tableData: Action[]; + let tableData: Action[] = []; if (isTransaction.value) { tableData = (await api.getTransaction(account.value)).actions; } else if (hasActions.value) { @@ -261,46 +260,21 @@ export default defineComponent({ } else { const page = paginationSettings.value.page; let limit = paginationSettings.value.rowsPerPage; - - let notified = accountsModel.value ?? ''; - let after = ''; - let before = ''; - if (toDateModel.value !== now) { - before = new Date(toDateModel.value).toISOString(); - } - if (fromDateModel.value !== '') { - after = new Date(fromDateModel.value).toISOString(); - } + const notified = accountsModel.value ?? ''; + const after = fromDateModel.value !== '' ? new Date(fromDateModel.value).toISOString() : ''; + const before = toDateModel.value !== now ? new Date(toDateModel.value).toISOString() : ''; const sort = paginationSettings.value.descending ? 'desc' : 'asc'; + const extras: {[key:string]:string} = {}; - let extras: {[key:string]:string} | null = tokenModel.value ? { 'act.account': tokenModel.value.contract } : null; - if (actionsModel.value) { - extras = extras ? { - ...extras, - 'act.name': actionsModel.value, - } : { - 'act.name': actionsModel.value, - }; - } - - if (page > 1 && currentFirstAction.value === 0) { - currentFirstAction.value = rows.value[0]?.action.global_sequence; + if (tokenModel.value) { + extras['act.account'] = tokenModel.value.contract; + // Increase limit to allow for filtering + limit = limit * 3; } - - if (currentFirstAction.value > 0) { - extras = extras ? { - ...extras, - 'global_sequence': '0-' + currentFirstAction.value.toString(), - } : { - 'global_sequence': '0-' + currentFirstAction.value.toString(), - }; + if (actionsModel.value) { + extras['act.name'] = actionsModel.value; } - // if token is selected, we need to get all transactions and filter them - // so we eventually will need more than the current page size - if (tokenModel.value) { - limit = 100; - } const response = await api.getTransactions({ page, limit, @@ -318,36 +292,42 @@ export default defineComponent({ if (tableData) { if (tokenModel.value) { tableData = tableData.filter( - item => (item.act.data as {quantity?:string}).quantity?.includes(tokenModel.value.symbol), + item => (item.act.data as {quantity?:string})?.quantity?.includes(tokenModel.value.symbol), ); - - // take only the first aginationSettings.value.rowsPerPage items - tableData = tableData.slice(0, paginationSettings.value.rowsPerPage); } - rows.value = tableData.map(item => ({ - name: item.trx_id, - transaction: { id: item.trx_id, type: 'transaction' }, - timestamp: item['@timestamp'] || item.timestamp, - action: item, - data: hasActions.value - ? { data: item.data, name: item.account } - : { data: item.act.data, name: item.act.name }, - actions: [ - { - name: item.trx_id, - transaction: { id: item.trx_id, type: 'transaction' }, - timestamp: item['@timestamp'], - action: item, - data: hasActions.value - ? { - data: item.data, - name: item.account, - } - : { data: item.act.data as unknown, name: item.act.name }, - }, - ], - })); + const flattenedData: TransactionTableRow[] = []; + tableData.forEach((action) => { + const actionsArray = action.act?.data ? [action] : []; + actionsArray.forEach((act) => { + flattenedData.push({ + name: act.trx_id, + transaction: { id: act.trx_id, type: 'transaction' }, + timestamp: act['@timestamp'] || act.timestamp, + action: act, + data: { + data: act.act.data, + name: act.act.name, + }, + actions: actionsArray.map(a => ({ + name: a.trx_id, + transaction: { id: a.trx_id, type: 'transaction' }, + timestamp: a['@timestamp'] || a.timestamp, + action: a, + data: { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + data: a.act.data, + name: a.act.name, + }, + })), + }); + }); + }); + + // Apply pagination after filtering + const startIndex = (paginationSettings.value.page - 1) * paginationSettings.value.rowsPerPage; + rows.value = flattenedData.slice(startIndex, startIndex + paginationSettings.value.rowsPerPage); + totalRows.value = flattenedData.length; } void filterRows(); }; From de400611869431c484915c173e5cdaf4f271bd63 Mon Sep 17 00:00:00 2001 From: Viterbo Date: Tue, 9 Jul 2024 22:12:56 -0300 Subject: [PATCH 2/2] retry to fetch the block and show error if it fails. Also added loading spinner --- src/components/BlockCard.vue | 42 +++++++++++++++------- src/pages/Block.vue | 69 +++++++++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/components/BlockCard.vue b/src/components/BlockCard.vue index efbeab91..406298b7 100644 --- a/src/components/BlockCard.vue +++ b/src/components/BlockCard.vue @@ -15,6 +15,10 @@ import { formatDate } from 'src/utils/string-utils'; export default defineComponent({ name: 'BlockCard', props: { + block_num: { + type: String, + required: true, + }, block: { type: Object as PropType, required: false, @@ -22,8 +26,10 @@ export default defineComponent({ }, }, setup(props) { + const loading = ref(true); const router = useRouter(); const q = useQuasar(); + const blockNum = computed(() => props.block_num); const Block = computed(() => props.block); const blockInfo = ref<{ key: string; value: string }[]>([]); async function nextBlock() { @@ -96,6 +102,7 @@ export default defineComponent({ }, { key: 'Actions', value: actionCount.toString() }, ]; + loading.value = false; } } watch(Block, () => { @@ -105,13 +112,14 @@ export default defineComponent({ setBlockData(); }); return { - block_num: computed(() => Block.value?.block_num || 0), nextBlock, previousBlock, numberWithCommas, formatDate, copy, blockInfo, + blockNum, + loading, }; }, }); @@ -154,7 +162,7 @@ export default defineComponent({
-
{{numberWithCommas(block_num)}}
+
{{numberWithCommas(parseInt(block_num))}}
- -
SUMMARY
+ + +
+ +
-
- +
diff --git a/src/pages/Block.vue b/src/pages/Block.vue index 32ccd470..221c1328 100644 --- a/src/pages/Block.vue +++ b/src/pages/Block.vue @@ -13,26 +13,51 @@ export default defineComponent({ const router = useRouter(); const found = ref(true); const block = ref(null); + const block_num = ref(route.params.block as string); const actions = ref([]); const tab = ref((route.query['tab'] as string) || 'actions'); + const tries = 3; + const error = ref(''); + // tryToLoadBlock is a function that tries to load a block from the API at least 3 times before giving up + const tryToLoadBlock = async (block_num: string) => { + error.value = ''; + let block = null; + for (let i = 0; i < tries; i++) { + try { + block = await api.getBlock(block_num); + break; + } catch (e) { + console.error(`Failed to load block ${block_num} on try ${i + 1}`); + if (i === tries - 1) { + throw e; + } + } + } + return block; + }; onMounted(async () => { // api get block and set block - block.value = await api.getBlock(route.params.block as string); - block.value.transactions.forEach((tr) => { - const act = tr.trx.transaction?.actions.map(act => ({ - ...act, - trx_id: tr.trx.id, - act: { - ...act.act, - name: act.name, - data: act.data, - account: act.account, - }, - '@timestamp': block.value.timestamp, - })); - actions.value = actions.value.concat(act); - }); - found.value = !!block.value; + try { + block.value = await tryToLoadBlock(block_num.value); + block.value.transactions.forEach((tr) => { + const act = tr.trx.transaction?.actions.map(act => ({ + ...act, + trx_id: tr.trx.id, + act: { + ...act.act, + name: act.name, + data: act.data, + account: act.account, + }, + '@timestamp': block.value.timestamp, + })); + actions.value = actions.value.concat(act); + }); + found.value = !!block.value; + } catch (e) { + found.value = false; + error.value = 'Unable to load block, try refreshing the page'; + } }); watch([tab], () => { void router.push({ @@ -48,6 +73,8 @@ export default defineComponent({ found, Actions: actions, block, + block_num, + error, }; }, components: { @@ -61,7 +88,12 @@ export default defineComponent({
- +
@@ -70,6 +102,9 @@ export default defineComponent({
block not found
+ +
{{ error }}
+