Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create Rollup filter & FilterPanel #496

Merged
merged 35 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
663957a
refactor(web): create Option type for Dropdown options
xFJA Aug 6, 2024
2e4d6a1
chore(web): update changeset
xFJA Aug 6, 2024
852efc5
refactor(web): use label in Dropdown selected option display
xFJA Aug 6, 2024
a8745ee
refactor(web): update Dropdown component main filename
xFJA Aug 19, 2024
177585e
refactor(web): remove nested /components folder in Dropdown
xFJA Aug 19, 2024
07c857f
feat(web): render value when no label in Dropdown
xFJA Aug 21, 2024
cfe321e
feat(web): add prefix slot to Dropdown option
xFJA Aug 8, 2024
16257bd
feat(web): add filter panel with rollup filter in PaginatedTable
xFJA Aug 8, 2024
0e972a5
chore(web): update changeset
xFJA Aug 11, 2024
aa84252
refactor(web): rename main PaginedTable filename
xFJA Aug 19, 2024
623b413
refactor(web): rename main FilersPanel filename
xFJA Aug 19, 2024
3e4f4d6
refactor(web): update RollupFilter component to fetch rollups from API
luis-herasme Aug 20, 2024
19c8482
feat(web): add filters to query params
xFJA Aug 21, 2024
693ff22
fix(web): pages number calculation in PaginatedTable
xFJA Aug 21, 2024
97040d3
fix(web): pages number calculation in PaginatedTable
xFJA Aug 21, 2024
2270db2
Merge branch 'main' into 490-refactor-dropdown
xFJA Aug 26, 2024
9b1926a
refactor(web): simplify dropdowns options
xFJA Aug 26, 2024
324549c
Merge branch '490-refactor-dropdown' into create-rollup-filter
xFJA Aug 26, 2024
553388b
feat(web): add clear button for filter
xFJA Aug 28, 2024
70e36e5
Separate Prisma enums to their own file (#523)
PJColombo Aug 28, 2024
f173b57
Abstract rollup addresses into its own package (#524)
PJColombo Aug 28, 2024
a707285
Merge branch 'main' into create-rollup-filter
PJColombo Aug 29, 2024
9bd7c35
chore: fix `@blobscan/rollups` version
PJColombo Aug 29, 2024
de3c235
refactor(web): display selected rollup icon on rollup dropdown
PJColombo Aug 29, 2024
5ff8f98
refactor(web): refactor `Filters` component
PJColombo Aug 29, 2024
8849eb6
feat(web): add support for filtering by no rollup
PJColombo Aug 29, 2024
2031a51
feat(web): add clear button to dropdown + make rollup filter clearable
PJColombo Aug 29, 2024
08c976a
chore: add changeset
PJColombo Aug 29, 2024
886b83c
refactor(web): extract query parameter logic into a custom hook
PJColombo Aug 30, 2024
7aa964c
fix(web): sync rollup filter dropdown with URL query parameter for co…
PJColombo Aug 30, 2024
7f8a525
feat(rollups): return rollup's address and name when fetching chain's…
PJColombo Aug 30, 2024
dbe1906
chore: add changeset
PJColombo Aug 30, 2024
df550e2
fix(web): use rollup's address when filtering elements by rollup
PJColombo Aug 30, 2024
390c8cb
chore: add changeset
PJColombo Aug 30, 2024
27c687e
fix(web): ensure rollup address query parameter stays consistent with…
PJColombo Aug 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/odd-pumpkins-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/rollups": minor
---

Added support for retrieving rollups by their addresses
5 changes: 5 additions & 0 deletions .changeset/perfect-mirrors-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": patch
---

Refactored Dropdown options using a new type to allow add new elements to the Option display
5 changes: 5 additions & 0 deletions .changeset/quiet-experts-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/rollups": minor
---

Added support for retrieving all chain's available rollups
5 changes: 5 additions & 0 deletions .changeset/sixty-parrots-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/db": minor
---

Exposed Prisma enums from a separated file
5 changes: 5 additions & 0 deletions .changeset/smooth-trains-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": minor
---

Added rollup filter to blobs, blocks and transactions views
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ coverage
**/prisma/db.sqlite
**/prisma/db.sqlite-journal

# Prisma generated files
packages/db/prisma/enums

# next.js
.next/
out/
Expand Down
1 change: 1 addition & 0 deletions apps/docs/src/app/docs/codebase-overview/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Here you can find all the shared packages used by the apps:
| [`@blobscan/test`](https://github.com/Blobscan/blobscan/tree/next/packages/test) |  Shared test utilities and fixtures. |
|  [`@blobscan/zod`](https://github.com/Blobscan/blobscan/tree/next/packages/zod) |  Shared [Zod](https://zod.dev) schemas and utilities. |
|  [`@blobscan/eth-format`](https://github.com/Blobscan/blobscan/tree/next/packages/eth-format) |  Provides utility functions for handling Ethereum value conversions and formatting. |
|  [`@blobscan/rollups`](https://github.com/Blobscan/blobscan/tree/next/packages/rollups) |  A utility that provides a comprehensive list of all rollups and their associated addresses supported by Blobscan, along with functions to retrieve them easily. |

### Tooling

Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@blobscan/env": "workspace:^0.0.1",
"@blobscan/eth-units": "workspace:^0.0.1",
"@blobscan/open-telemetry": "workspace:^0.0.8",
"@blobscan/rollups": "workspace:^0.2.1",
"@fontsource/inter": "^4.5.15",
"@fontsource/public-sans": "^4.5.12",
"@headlessui/react": "^2.1.0",
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/components/Cards/SurfaceCards/BlobCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ const BlobCard: FC<BlobCardProps> = ({
</div>
{transactions
?.filter((tx) => !!tx.rollup)
.map(({ rollup }) => (
<RollupIcon key={rollup} rollup={rollup as Rollup} />
))}
.map(({ rollup }) =>
rollup ? <RollupIcon key={rollup} rollup={rollup} /> : null
)}
</div>
) : (
<Skeleton width={isCompact ? undefined : 630} />
Expand Down
75 changes: 0 additions & 75 deletions apps/web/src/components/Dropdown.tsx

This file was deleted.

30 changes: 30 additions & 0 deletions apps/web/src/components/Dropdown/Option.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ListboxOption } from "@headlessui/react";

import type { Option as OptionProps } from ".";

export const Option: React.FC<OptionProps> = function (props) {
const { prefix, label, value } = props;
return (
<ListboxOption
className={({ focus }) =>
`relative cursor-pointer select-none px-4 py-2 ${
focus
? "bg-controlActive-light dark:bg-controlActive-dark dark:text-content-dark"
: "text-contentSecondary-light dark:text-contentSecondary-dark"
}`
}
value={props}
>
{({ selected }) => (
<div className="flex items-center gap-3">
{prefix && prefix}
<span
className={`block truncate text-sm ${selected ? "font-bold" : ""}`}
>
{label ? label : value}
</span>
</div>
)}
</ListboxOption>
);
};
71 changes: 71 additions & 0 deletions apps/web/src/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { ReactNode } from "react";
import {
Listbox,
ListboxButton,
ListboxOptions,
Transition,
} from "@headlessui/react";
import { ChevronUpDownIcon } from "@heroicons/react/24/outline";

import { Option } from "./Option";

export interface Option {
value: string | number;
label?: ReactNode;
prefix?: React.ReactNode;
}

export interface DropdownProps {
options: Option[];
selected: Option | null;
width?: string;
placeholder?: string;
onChange(newOption: Option): void;
}

const DEFAULT_WIDTH = "w-32";

export const Dropdown: React.FC<DropdownProps> = function ({
options,
selected,
width,
onChange,
placeholder = "Select",
}) {
return (
<Listbox value={selected} onChange={onChange}>
<div className="relative">
<ListboxButton
className={`relative h-9 ${
width ?? DEFAULT_WIDTH
} cursor-pointer rounded-lg border border-transparent bg-controlBackground-light pl-2 pr-8 text-left text-sm shadow-md hover:border hover:border-controlBackground-light focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white active:border-controlBorderHighlight-dark ui-open:border-controlActive-light dark:bg-controlBackground-dark dark:hover:border-controlBorderHighlight-dark dark:ui-open:border-controlActive-dark`}
>
<span className="block truncate align-middle font-normal">
{selected
? selected.label
? selected.label
: selected.value
: placeholder}
</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-icon-light dark:text-icon-dark"
aria-hidden="true"
/>
</span>
</ListboxButton>
<Transition
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<ListboxOptions className="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-controlBackground-light py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-controlBackground-dark sm:text-sm">
{options.map((option, id) => (
<Option {...option} key={id} />
))}
</ListboxOptions>
</Transition>
</div>
</Listbox>
);
};
32 changes: 32 additions & 0 deletions apps/web/src/components/Filters/RollupFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { FC } from "react";

import { Rollup as Rollups } from "@blobscan/api/enums";

import { Dropdown } from "~/components/Dropdown";
import type { DropdownProps } from "~/components/Dropdown";
import { RollupIcon } from "~/components/RollupIcon";
import type { Rollup } from "~/types";
import { capitalize } from "~/utils";

type RollupFilterProps = Pick<DropdownProps, "onChange" | "selected">;

export const RollupFilter: FC<RollupFilterProps> = function ({
onChange,
selected,
}) {
return (
<>
<Dropdown
selected={selected}
options={Object.values(Rollups).map((rollup) => ({
value: rollup.toLowerCase(),
label: capitalize(rollup),
prefix: <RollupIcon rollup={rollup.toLowerCase() as Rollup} />,
}))}
PJColombo marked this conversation as resolved.
Show resolved Hide resolved
onChange={onChange}
placeholder="Rollup"
width="w-40"
/>
</>
);
};
66 changes: 66 additions & 0 deletions apps/web/src/components/Filters/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState } from "react";
import type { FC } from "react";
import { useRouter } from "next/router";

import { Button } from "~/components/Button";
import type { Option } from "../Dropdown";
import { RollupFilter } from "./RollupFilter";

interface FiltersState {
rollup: Option | null;
}

export const Filters: FC = function () {
const [formData, setFormData] = useState<FiltersState>({
rollup: null,
});
const router = useRouter();

const allowToFilter = !!formData.rollup;

const handleSubmit = () => {
if (formData.rollup) {
router.push({
pathname: router.pathname,
query: {
...router.query,
rollup: formData.rollup.value,
},
});
}
};

const handleClear = () => {
router.push({ pathname: router.pathname, query: undefined });
setFormData({ rollup: null });
};

const handleRollupFilterChange = (newRollup: Option) => {
setFormData((prevState) => ({ ...prevState, rollup: newRollup }));
};

return (
<form
className="flex flex-col justify-between gap-2 rounded-lg bg-slate-50 p-2 dark:bg-primary-900 sm:flex-row"
onSubmit={handleSubmit}
>
<RollupFilter
selected={formData.rollup}
onChange={handleRollupFilterChange}
/>
<div className="flex flex-row gap-2">
<Button
label="Clear"
variant="outline"
onClick={handleClear}
disabled={!allowToFilter}
/>
<Button
label="Filter"
onClick={handleSubmit}
disabled={!allowToFilter}
/>
</div>
</form>
);
};
18 changes: 13 additions & 5 deletions apps/web/src/components/Layouts/PaginatedListLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ export type PaginatedListLayoutProps = {
emptyState?: ReactNode;
};

const PAGE_SIZES = [10, 25, 50, 100];
const PAGE_SIZES_OPTIONS: DropdownProps["options"] = [
{ value: 10 },
{ value: 25 },
{ value: 50 },
{ value: 100 },
];

export const PaginatedListLayout: FC<PaginatedListLayoutProps> = function ({
header,
Expand All @@ -42,7 +47,7 @@ export const PaginatedListLayout: FC<PaginatedListLayoutProps> = function ({
const hasItems = !items || items.length;

const handlePageSizeSelection = useCallback<DropdownProps["onChange"]>(
(newPageSize: number) =>
({ value: newPageSize }) =>
void router.push({
pathname: router.pathname,
query: {
Expand All @@ -51,7 +56,10 @@ export const PaginatedListLayout: FC<PaginatedListLayoutProps> = function ({
* Update the selected page to a lower value if we require less pages to show the
* new amount of elements per page.
*/
p: Math.min(Math.ceil(totalItems ?? 0 / newPageSize), page),
p: Math.min(
Math.ceil(totalItems ?? 0 / (newPageSize as number)),
page
),
ps: newPageSize,
},
}),
Expand Down Expand Up @@ -110,8 +118,8 @@ export const PaginatedListLayout: FC<PaginatedListLayoutProps> = function ({
<div className="flex items-center justify-start gap-2">
Displayed items:
<Dropdown
items={PAGE_SIZES}
selected={pageSize}
options={PAGE_SIZES_OPTIONS}
selected={{ value: pageSize, label: pageSize.toString() }}
width="w-full"
onChange={handlePageSizeSelection}
/>
Expand Down
Loading
Loading