Skip to content

Commit

Permalink
fix PeeringDB link rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
thatmattlove committed Mar 24, 2024
1 parent 0cbec73 commit 19bdfe7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 38 deletions.
14 changes: 13 additions & 1 deletion hyperglass/models/config/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
# Standard Library
import typing as t
from pathlib import Path
import urllib.parse

# Third Party
from pydantic import Field, ConfigDict, ValidationInfo, field_validator
from pydantic import Field, ConfigDict, ValidationInfo, field_validator, HttpUrl

# Project
from hyperglass.settings import Settings
Expand Down Expand Up @@ -108,6 +109,17 @@ def validate_plugins(cls: "Params", value: t.List[str]) -> t.List[str]:
return [str(f) for f in matching_plugins]
return []

@field_validator("web", mode="after")
@classmethod
def validate_web(cls, web: Web, info: ValidationInfo) -> Web:
"""String-format Link URLs."""
for link in web.links:
url = urllib.parse.unquote(str(link.url), encoding="utf-8", errors="replace").format(
primary_asn=info.data.get("primary_asn", "65000")
)
link.url = HttpUrl(url)
return web

def common_plugins(self) -> t.Tuple[Path, ...]:
"""Get all validated external common plugins as Path objects."""
return tuple(Path(p) for p in self.plugins)
Expand Down
63 changes: 26 additions & 37 deletions hyperglass/ui/components/footer/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Flex, HStack, useToken } from '@chakra-ui/react';
import { useMemo } from 'react';
import { useConfig } from '~/context';
import { DynamicIcon } from '~/elements';
import { useBreakpointValue, useColorValue, useMobile, useStrf } from '~/hooks';
import { useBreakpointValue, useColorValue, useMobile } from '~/hooks';
import { isLink, isMenu } from '~/types';
import { FooterButton } from './button';
import { ColorModeToggle } from './color-mode';
Expand All @@ -11,7 +11,9 @@ import { FooterLink } from './link';
import type { ButtonProps, LinkProps } from '@chakra-ui/react';
import type { Link, Menu } from '~/types';

function buildItems(links: Link[], menus: Menu[]): [(Link | Menu)[], (Link | Menu)[]] {
type MenuItems = (Link | Menu)[];

function buildItems(links: Link[], menus: Menu[]): [MenuItems, MenuItems] {
const leftLinks = links.filter(link => link.side === 'left');
const leftMenus = menus.filter(menu => menu.side === 'left');
const rightLinks = links.filter(link => link.side === 'right');
Expand All @@ -22,8 +24,23 @@ function buildItems(links: Link[], menus: Menu[]): [(Link | Menu)[], (Link | Men
return [left, right];
}

const LinkOnSide = (props: { item: ArrayElement<MenuItems>; side: 'left' | 'right' }) => {
const { item, side } = props;
if (isLink(item)) {
const icon: Partial<ButtonProps & LinkProps> = {};

if (item.showIcon) {
icon.rightIcon = <DynamicIcon icon={{ go: 'GoLinkExternal' }} />;
}
return <FooterLink key={item.title} href={item.url} title={item.title} {...icon} />;
}
if (isMenu(item)) {
return <FooterButton key={item.title} side={side} content={item.content} title={item.title} />;
}
};

export const Footer = (): JSX.Element => {
const { web, content, primaryAsn } = useConfig();
const { web, content } = useConfig();

const footerBg = useColorValue('blackAlpha.50', 'whiteAlpha.100');
const footerColor = useColorValue('black', 'white');
Expand All @@ -34,8 +51,6 @@ export const Footer = (): JSX.Element => {

const [left, right] = useMemo(() => buildItems(web.links, web.menus), [web.links, web.menus]);

const strF = useStrf();

return (
<HStack
px={6}
Expand All @@ -51,39 +66,13 @@ export const Footer = (): JSX.Element => {
overflowY={{ base: 'auto', lg: 'unset' }}
justifyContent={{ base: 'center', lg: 'space-between' }}
>
{left.map(item => {
if (isLink(item)) {
const url = strF(item.url, { primaryAsn }, '/');
const icon: Partial<ButtonProps & LinkProps> = {};

if (item.showIcon) {
icon.rightIcon = <DynamicIcon icon={{ go: 'GoLinkExternal' }} />;
}
return <FooterLink key={item.title} href={url} title={item.title} {...icon} />;
}
if (isMenu(item)) {
return (
<FooterButton key={item.title} side="left" content={item.content} title={item.title} />
);
}
})}
{left.map(item => (
<LinkOnSide key={item.title} item={item} side="left" />
))}
{!isMobile && <Flex p={0} flex="1 0 auto" maxWidth="100%" mr="auto" />}
{right.map(item => {
if (isLink(item)) {
const url = strF(item.url, { primaryAsn }, '/');
const icon: Partial<ButtonProps & LinkProps> = {};

if (item.showIcon) {
icon.rightIcon = <DynamicIcon icon={{ go: 'GoLinkExternal' }} />;
}
return <FooterLink key={item.title} href={url} title={item.title} {...icon} />;
}
if (isMenu(item)) {
return (
<FooterButton key={item.title} side="right" content={item.content} title={item.title} />
);
}
})}
{right.map(item => (
<LinkOnSide key={item.title} item={item} side="right" />
))}
{web.credit.enable && (
<FooterButton
key="credit"
Expand Down
3 changes: 3 additions & 0 deletions hyperglass/ui/types/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export declare global {

type Swap<T, K extends keyof T, V> = Record<K, V> & Omit<T, K>;

type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

type RPKIState = 0 | 1 | 2 | 3;

type ResponseLevel = 'success' | 'warning' | 'error' | 'danger';
Expand Down

0 comments on commit 19bdfe7

Please sign in to comment.