Skip to content

Commit

Permalink
fix: different no transaction messages for non-existing and empty bat…
Browse files Browse the repository at this point in the history
…ches/blocks (#107)

# What ❔

Different _no transaction_ messages for non-existing and empty
batches/blocks:
Empty batch:
<img width="1259" alt="image"
src="https://github.com/matter-labs/block-explorer/assets/6553665/b3f8d9fc-dee8-4178-91c3-26eaff3be660">
Non-existing batch:
<img width="1263" alt="image"
src="https://github.com/matter-labs/block-explorer/assets/6553665/da083f5f-c887-41f0-9173-0c51064fca91">

## Why ❔

For better UX we want to show different _no transaction_ messages in
different cases:
`This Batch doesn’t have any transactions` - for empty batch,
`This Batch has not been created or sealed yet` - for non-existing
batch,
same for blocks.

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [X] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [X] Tests for the changes have been added / updated.
  • Loading branch information
vasyl-ivanchuk authored and pcheremu committed Feb 15, 2024
1 parent 1972d80 commit 8f70d0d
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 122 deletions.
21 changes: 15 additions & 6 deletions packages/app/src/components/batches/InfoTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const props = defineProps({
type: Object as PropType<BatchDetails | null>,
default: null,
},
batchNumber: {
type: String,
required: true,
},
loading: {
type: Boolean,
default: true,
Expand All @@ -45,15 +49,20 @@ const tableInfoItems = computed(() => {
component?: Component;
url?: string;
};
if (!props.batch) {
return [];
}
let tableItems: InfoTableItem[] = [
{
label: t("batches.index"),
tooltip: t("batches.indexTooltip"),
value: props.batch.number,
value: props.batchNumber,
},
];
if (!props.batch) {
return [tableItems];
}
tableItems.push(
{
label: t("batches.size"),
tooltip: t("batches.sizeTooltip"),
Expand All @@ -70,8 +79,8 @@ const tableInfoItems = computed(() => {
tooltip: t("batches.rootHashTooltip"),
value: props.batch.rootHash ? { value: props.batch.rootHash } : t("batches.noRootHashYet"),
component: props.batch.rootHash ? CopyContent : undefined,
},
];
}
);
for (const [key, timeKey] of [
["commitTxHash", "committedAt", "notYetCommitted"],
["proveTxHash", "provenAt", "notYetProven"],
Expand Down
27 changes: 12 additions & 15 deletions packages/app/src/components/batches/TransactionEmptyState.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
<template>
<div class="transactions-empty-state">
<EmptyState>
<EmptyState class="empty-state">
<template #title>
{{ t("batches.transactionTable.notFound.title") }}
</template>
<template #description>
<div class="transactions-empty-description">
{{ t("batches.transactionTable.notFound.subtitle") }}
</div>
{{ batchExists ? t("batches.transactionTable.noTransactions") : t("batches.transactionTable.batchNotFound") }}
</template>
<template #description><span></span></template>
</EmptyState>
</div>
</template>
Expand All @@ -19,16 +15,17 @@ import { useI18n } from "vue-i18n";
import EmptyState from "@/components/common/EmptyState.vue";
const { t } = useI18n();
defineProps({
batchExists: {
type: Boolean,
required: true,
},
});
</script>

<style scoped lang="scss">
.transactions-empty-state {
@apply flex py-8 lg:justify-center;
.transactions-empty-description {
@apply max-w-[24rem] whitespace-pre-line;
a {
@apply text-neutral-400;
}
}
.empty-state {
@apply items-center justify-center whitespace-normal py-10;
}
</style>
17 changes: 12 additions & 5 deletions packages/app/src/components/blocks/InfoTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const props = defineProps({
type: Object as PropType<Block | null>,
default: null,
},
blockNumber: {
type: String,
required: true,
},
loading: {
type: Boolean,
default: true,
Expand All @@ -52,11 +56,13 @@ const tableInfoItems = computed(() => {
disabledTooltip?: string;
};
};
let tableItems: InfoTableItem[] = [
{ label: t("blocks.table.blockNumber"), tooltip: t("blocks.table.blockNumberTooltip"), value: props.blockNumber },
];
if (!props.block) {
return [];
return [tableItems];
}
let tableItems: InfoTableItem[] = [
{ label: t("blocks.table.blockNumber"), tooltip: t("blocks.table.blockNumberTooltip"), value: props.block.number },
tableItems.push(
{
label: t("blocks.table.blockSize"),
tooltip: t("blocks.table.blockSizeTooltip"),
Expand Down Expand Up @@ -95,8 +101,8 @@ const tableInfoItems = computed(() => {
tooltip: t("blocks.table.timestampTooltip"),
value: { value: props.block.timestamp },
component: TimeField,
},
];
}
);
for (const [key, timeKey] of [
["commitTxHash", "committedAt", "notYetCommitted"],
["proveTxHash", "provenAt", "notYetProven"],
Expand Down Expand Up @@ -135,6 +141,7 @@ const tableInfoItems = computed(() => {
.two-section-view {
@apply grid gap-4 pb-1.5 lg:grid-cols-2;
}
.hide-mobile {
@apply hidden lg:block;
}
Expand Down
30 changes: 12 additions & 18 deletions packages/app/src/components/blocks/TransactionEmptyState.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<template>
<div class="transactions-empty-state">
<EmptyState>
<EmptyState class="empty-state">
<template #title>
{{ t("blocks.transactionTable.notFound.title") }}
</template>
<template #description>
<div class="transactions-empty-description">
{{ t("blocks.transactionTable.notFound.subtitle") }}
<a :href="t('blocks.transactionTable.notFound.url')" target="_blank">
{{ t("blocks.transactionTable.notFound.urlTitle") }}
</a>
</div>
{{ blockExists ? t("blocks.transactionTable.noTransactions") : t("blocks.transactionTable.blockNotFound") }}
</template>
<template #description><span></span></template>
</EmptyState>
</div>
</template>
Expand All @@ -22,16 +15,17 @@ import { useI18n } from "vue-i18n";
import EmptyState from "@/components/common/EmptyState.vue";
const { t } = useI18n();
defineProps({
blockExists: {
type: Boolean,
required: true,
},
});
</script>

<style scoped lang="scss">
.transactions-empty-state {
@apply flex py-8 lg:justify-center;
.transactions-empty-description {
@apply max-w-[24rem] whitespace-normal;
a {
@apply text-neutral-400;
}
}
.empty-state {
@apply items-center justify-center whitespace-normal py-10;
}
</style>
16 changes: 5 additions & 11 deletions packages/app/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,8 @@
"transactionTable": {
"title": "Block Transactions",
"showMore": "Show more transactions ->",
"notFound": {
"title": "This Block doesn't have any transactions",
"subtitle": "We always have a zero block at the end of the batch. Want to know why?",
"urlTitle": "Visit our docs page",
"url": "https://docs-v2-zksync.web.app/dev/developer-guides/transactions/blocks.html#blocks-in-zksync-2-0"
}
"noTransactions": "This Block doesn't have any transactions",
"blockNotFound": "This Block has not been created or sealed yet"
}
},
"transfers": {
Expand Down Expand Up @@ -258,10 +254,8 @@
"transactionTable": {
"title": "Batch Transactions",
"error": "Something went wrong",
"notFound": {
"title": "This Batch doesn't have any transactions",
"subtitle": "We can't find transactions for this batch \n We'll fix it in a moment; please refresh the page"
}
"noTransactions": "This Batch doesn't have any transactions",
"batchNotFound": "This Batch has not been created or sealed yet"
},
"table": {
"status": "Status",
Expand Down Expand Up @@ -409,7 +403,7 @@
},
"contractVerification": {
"title": "Smart Contract Verification",
"subtitle": "Source code verification provides transparency for users interacting with smart contracts. By uploading the source code, zkScan will match the compiled code with that on the blockchain.",
"subtitle": "Source code verification provides transparency for users interacting with smart contracts. By uploading the source code, Era Explorer will match the compiled code with that on the blockchain.",
"resources": {
"title": "You can also verify your smart-contract using {hardhat}",
"links": {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/locales/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
},
"contractVerification": {
"title": "Верифікація Смарт контракту",
"subtitle": "Перевірка вихідного коду забезпечує прозорість для користувачів, які взаємодіють зі смарт-контрактами. Завантаживши вихідний код, zkScan зіставить скомпільований код із кодом у блокчейні.",
"subtitle": "Перевірка вихідного коду забезпечує прозорість для користувачів, які взаємодіють зі смарт-контрактами. Завантаживши вихідний код, Era Explorer зіставить скомпільований код із кодом у блокчейні.",
"form": {
"title": "Деталі Контракту",
"compilationInfo": "Деталі компіляції",
Expand Down
12 changes: 5 additions & 7 deletions packages/app/src/views/BatchView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
<Breadcrumbs :items="breadcrumbItems" />
<SearchForm class="search-form" />
</div>
<Title v-if="!batchPending && batchItem" :title="t('batches.batchNumber')" :value="id">
<Title v-if="!batchPending" :title="t('batches.batchNumber')" :value="id">
{{ parseInt(id) }}
</Title>
<Spinner v-else size="md" />

<div class="tables-container">
<BatchTable class="batch-table" :loading="batchPending" :batch="batchItem" />
<BatchTable class="batch-table" :loading="batchPending" :batch="batchItem" :batch-number="id" />

<div v-if="batchItem" ref="transactionsContainer">
<div ref="transactionsContainer">
<h2 class="table-transaction-title">{{ t("batches.transactionTable.title") }}</h2>
<TransactionsTable class="transactions-table" :search-params="transactionsSearchParams">
<template #not-found>
<TransactionEmptyState />
<TransactionEmptyState :batch-exists="!!batchItem" />
</template>
</TransactionsTable>
</div>
Expand Down Expand Up @@ -49,7 +49,7 @@ import { isBlockNumber } from "@/utils/validators";
const { t } = useI18n();
const { useNotFoundView, setNotFoundView } = useNotFound();
const { setNotFoundView } = useNotFound();
const { getById, batchItem, isRequestPending: batchPending, isRequestFailed: batchFailed } = useBatch();
const props = defineProps({
Expand Down Expand Up @@ -89,8 +89,6 @@ const transactionsSearchParams = computed(() => ({
l1BatchNumber: parseInt(props.id),
}));
useNotFoundView(batchPending, batchFailed, batchItem);
watchEffect(() => {
if (!props.id || !isBlockNumber(props.id)) {
return setNotFoundView();
Expand Down
12 changes: 5 additions & 7 deletions packages/app/src/views/BlockView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
<Breadcrumbs :items="breadcrumbItems" />
<SearchForm class="search-form" />
</div>
<Title v-if="!blockPending && blockItem" :title="t('blocks.blockNumber')" :value="id">
<Title v-if="!blockPending" :title="t('blocks.blockNumber')" :value="id">
{{ parseInt(id) }}
</Title>
<Spinner v-else size="md" />
<div class="tables-container">
<div>
<BlockTable class="block-table" :loading="blockPending" :block="blockItem" />
<BlockTable class="block-table" :loading="blockPending" :block="blockItem" :block-number="id" />
</div>
<div v-if="blockItem">
<div>
<h2 class="table-transaction-title">{{ t("blocks.transactionTable.title") }}</h2>
<TransactionsTable
class="transactions-table"
:search-params="transactionsSearchParams"
data-testid="block-transactions-table"
>
<template #not-found>
<TransactionEmptyState />
<TransactionEmptyState :block-exists="!!blockItem" />
</template>
</TransactionsTable>
</div>
Expand Down Expand Up @@ -53,7 +53,7 @@ import { isBlockNumber } from "@/utils/validators";
const { t } = useI18n();
const { useNotFoundView, setNotFoundView } = useNotFound();
const { setNotFoundView } = useNotFound();
const { getById, blockItem, isRequestPending: blockPending, isRequestFailed: blockFailed } = useBlock();
const props = defineProps({
Expand Down Expand Up @@ -81,8 +81,6 @@ const transactionsSearchParams = computed(() => ({
blockNumber: parseInt(props.id),
}));
useNotFoundView(blockPending, blockFailed, blockItem);
watchEffect(() => {
if (!props.id || !isBlockNumber(props.id)) {
return setNotFoundView();
Expand Down
31 changes: 31 additions & 0 deletions packages/app/tests/components/batches/InfoTable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe("InfoTable:", () => {
},
props: {
batch: batchItem,
batchNumber: batchItem.number.toString(),
loading: false,
},
});
Expand Down Expand Up @@ -118,13 +119,41 @@ describe("InfoTable:", () => {

wrapper.unmount();
});

describe("when batch is not set", () => {
it("renders only batch number", () => {
const wrapper = mount(InfoTable, {
global: {
stubs: {
InfoTooltip: { template: "<div><slot /></div>" },
},
plugins: [i18n],
},
props: {
batchNumber: batchItem.number.toString(),
loading: false,
},
});

const rowArray = wrapper.findAll("tr");
expect(rowArray.length).toBe(1);

const batchIndex = rowArray[0].findAll("td");
expect(batchIndex[0].find(".batch-info-field-label").text()).toBe(i18n.global.t("batches.index"));
expect(batchIndex[0].findComponent(InfoTooltip).text()).toBe(i18n.global.t("batches.indexTooltip"));
expect(batchIndex[1].text()).toBe("42");
wrapper.unmount();
});
});

it("renders loading state", () => {
const wrapper = mount(InfoTable, {
global: {
plugins: [i18n],
},
props: {
loading: true,
batchNumber: batchItem.number.toString(),
},
});
expect(wrapper.findAll(".content-loader").length).toBe(20);
Expand All @@ -141,6 +170,7 @@ describe("InfoTable:", () => {
props: {
batch: batchItem,
loading: false,
batchNumber: batchItem.number.toString(),
},
});

Expand Down Expand Up @@ -175,6 +205,7 @@ describe("InfoTable:", () => {
},
props: {
batch: batchItem,
batchNumber: batchItem.number.toString(),
loading: false,
},
});
Expand Down
Loading

0 comments on commit 8f70d0d

Please sign in to comment.