From 65a4607101704ec2e9410198ec41bbeb23b84564 Mon Sep 17 00:00:00 2001 From: PJColombo Date: Fri, 14 Feb 2025 19:01:20 +0100 Subject: [PATCH 1/3] chore(web): parse `PUBLIC_SUPPORTED_NETWORKS` env var --- apps/web/src/env.mjs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/web/src/env.mjs b/apps/web/src/env.mjs index 2d99e65e1..a2dc0eed0 100644 --- a/apps/web/src/env.mjs +++ b/apps/web/src/env.mjs @@ -17,6 +17,11 @@ const booleanSchema = z .refine((s) => s === "true" || s === "false") .transform((s) => s === "true"); +const publicSupportedNetwork = z.object({ + label: z.string(), + href: z.string().url(), +}); + const clientEnvVars = { PUBLIC_BEACON_BASE_URL: z.string().url().default("https://beaconcha.in"), PUBLIC_EXPLORER_BASE_URL: z.string().url().default("https://etherscan.io"), @@ -28,7 +33,19 @@ const clientEnvVars = { .string() .default( '[{"label":"Ethereum Mainnet","href":"https://blobscan.com/"},{"label":"Gnosis","href":"https://gnosis.blobscan.com/"},{"label":"Holesky Testnet","href":"https://holesky.blobscan.com/"},{"label":"Sepolia Testnet","href":"https://sepolia.blobscan.com/"}]' - ), + ) + .transform((value) => JSON.parse(value)) + .transform((value) => { + const res = z.array(publicSupportedNetwork).safeParse(value); + + if (!res.success) { + throw new Error(`Failed to parse PUBLIC_SUPPORTED_NETWORKS`, { + cause: res.error, + }); + } + + return res.data; + }), PUBLIC_VERCEL_ANALYTICS_ENABLED: booleanSchema.default("false"), }; From 2dcdd8dd05d47066381f099ba0e1f7db16e5c1b0 Mon Sep 17 00:00:00 2001 From: PJColombo Date: Fri, 14 Feb 2025 19:02:26 +0100 Subject: [PATCH 2/3] fix(web): prevent skeleton display in navigation items component regardless of env var loading --- apps/web/src/components/NavigationMenus.tsx | 28 ++++------ .../src/components/SidebarNavigationMenu.tsx | 56 ++++++++----------- apps/web/src/{components => }/content.tsx | 15 +++-- apps/web/src/pages/block/[id].tsx | 2 +- 4 files changed, 44 insertions(+), 57 deletions(-) rename apps/web/src/{components => }/content.tsx (85%) diff --git a/apps/web/src/components/NavigationMenus.tsx b/apps/web/src/components/NavigationMenus.tsx index 665fcccbc..c8568ddd7 100644 --- a/apps/web/src/components/NavigationMenus.tsx +++ b/apps/web/src/components/NavigationMenus.tsx @@ -8,30 +8,22 @@ import { Transition, } from "@headlessui/react"; import { ChevronDownIcon } from "@heroicons/react/24/outline"; -import Skeleton from "react-loading-skeleton"; import { useHover } from "~/hooks/useHover"; import { useEnv } from "~/providers/Env"; -import type { ExpandibleNavigationItem, NavigationItem } from "./content"; -import { getNavigationItems, isExpandibleNavigationItem } from "./content"; +import type { ExpandibleNavigationItem, NavigationItem } from "../content"; +import { getNavigationItems, isExpandibleNavigationItem } from "../content"; export const NavigationMenus: FC = () => { const { env } = useEnv(); - - const navigationItems = useMemo(() => { - const networkName = env ? env.PUBLIC_NETWORK_NAME : undefined; - const publicSupportedNetworks = env - ? env.PUBLIC_SUPPORTED_NETWORKS - : undefined; - - return networkName && publicSupportedNetworks - ? getNavigationItems(networkName, publicSupportedNetworks) - : undefined; - }, [env]); - - if (!navigationItems) { - return ; - } + const navigationItems = useMemo( + () => + getNavigationItems({ + networkName: env?.PUBLIC_NETWORK_NAME, + publicSupportedNetworks: env?.PUBLIC_SUPPORTED_NETWORKS, + }), + [env] + ); return (
diff --git a/apps/web/src/components/SidebarNavigationMenu.tsx b/apps/web/src/components/SidebarNavigationMenu.tsx index 8b38574f1..424e881f0 100644 --- a/apps/web/src/components/SidebarNavigationMenu.tsx +++ b/apps/web/src/components/SidebarNavigationMenu.tsx @@ -4,37 +4,33 @@ import { usePathname } from "next/navigation"; import { ChevronDownIcon } from "@heroicons/react/24/outline"; import { Bars3Icon } from "@heroicons/react/24/solid"; import cn from "classnames"; -import Skeleton from "react-loading-skeleton"; import { useEnv } from "~/providers/Env"; +import type { ExpandibleNavigationItem, NavigationItem } from "../content"; +import { isExpandibleNavigationItem, getNavigationItems } from "../content"; import { BlobscanLogo } from "./BlobscanLogo"; import { Collapsable } from "./Collapsable"; import { IconButton } from "./IconButton"; import { Rotable } from "./Rotable"; import { SidePanel, useSidePanel } from "./SidePanel"; import { ThemeModeButton } from "./ThemeModeButton"; -import type { ExpandibleNavigationItem, NavigationItem } from "./content"; -import { isExpandibleNavigationItem, getNavigationItems } from "./content"; export function SidebarNavigationMenu({ className }: { className?: string }) { + const { env } = useEnv(); const [open, setOpen] = useState(false); + const navigationItems = useMemo( + () => + getNavigationItems({ + networkName: env?.PUBLIC_NETWORK_NAME, + publicSupportedNetworks: env?.PUBLIC_SUPPORTED_NETWORKS, + }), + [env] + ); const openSidebar = useCallback(() => setOpen(true), []); const closeSidebar = useCallback(() => setOpen(false), []); - const { env } = useEnv(); - - const navigationItems = useMemo(() => { - const networkName = env ? env.PUBLIC_NETWORK_NAME : undefined; - const publicSupportedNetworks = env - ? env.PUBLIC_SUPPORTED_NETWORKS - : undefined; - return networkName && publicSupportedNetworks - ? getNavigationItems(networkName, publicSupportedNetworks) - : undefined; - }, [env]); - return (
@@ -44,24 +40,20 @@ export function SidebarNavigationMenu({ className }: { className?: string }) {
- {navigationItems ? ( - navigationItems.map((item, i) => - isExpandibleNavigationItem(item) ? ( - - ) : ( - - ) + {navigationItems.map((item, i) => + isExpandibleNavigationItem(item) ? ( + + ) : ( + ) - ) : ( - )}
diff --git a/apps/web/src/components/content.tsx b/apps/web/src/content.tsx similarity index 85% rename from apps/web/src/components/content.tsx rename to apps/web/src/content.tsx index 10333e27e..c8329359d 100644 --- a/apps/web/src/components/content.tsx +++ b/apps/web/src/content.tsx @@ -58,10 +58,13 @@ export function isExpandibleNavigationItem( return typeof item === "object" && item !== null && "items" in item; } -export const getNavigationItems = ( - networkName: string, - publicSupportedNetworks: string -): Array => { +export const getNavigationItems = ({ + networkName, + publicSupportedNetworks, +}: { + networkName?: string; + publicSupportedNetworks?: ExpandibleNavigationSubItem[]; +}): Array => { return [ { label: "Blockchain", @@ -84,7 +87,7 @@ export const getNavigationItems = ( { label: "Networks", icon: , - items: JSON.parse(publicSupportedNetworks || "[]"), + items: publicSupportedNetworks ?? [], }, { label: "Stats", @@ -94,7 +97,7 @@ export const getNavigationItems = ( { label: "API", icon: , - href: resolveApiUrl(networkName), + href: networkName ? resolveApiUrl(networkName) : "#", }, { label: "Docs", diff --git a/apps/web/src/pages/block/[id].tsx b/apps/web/src/pages/block/[id].tsx index 3cab548cd..7797bb1e0 100644 --- a/apps/web/src/pages/block/[id].tsx +++ b/apps/web/src/pages/block/[id].tsx @@ -13,8 +13,8 @@ import type { DetailsLayoutProps } from "~/components/Layouts/DetailsLayout"; import { Link } from "~/components/Link"; import { NavArrows } from "~/components/NavArrows"; import { BlockStatus } from "~/components/Status"; -import { getFirstBlobNumber } from "~/components/content"; import { api } from "~/api-client"; +import { getFirstBlobNumber } from "~/content"; import NextError from "~/pages/_error"; import { useEnv } from "~/providers/Env"; import type { BlockWithExpandedBlobsAndTransactions } from "~/types"; From 15bf32eade9ad6da110351637005a344c28ba9c7 Mon Sep 17 00:00:00 2001 From: PJColombo Date: Fri, 14 Feb 2025 19:12:22 +0100 Subject: [PATCH 3/3] chore: add changeset --- .changeset/great-baboons-learn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/great-baboons-learn.md diff --git a/.changeset/great-baboons-learn.md b/.changeset/great-baboons-learn.md new file mode 100644 index 000000000..4ed264977 --- /dev/null +++ b/.changeset/great-baboons-learn.md @@ -0,0 +1,5 @@ +--- +"@blobscan/web": patch +--- + +Removed skeleton display from navigation items component if the env vars are not set