From 604af14e01e0660ad2f82e8f11064f111f6f9961 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 14 May 2024 07:26:54 -0700 Subject: [PATCH] feat(frontend): admin ui changes (#2716) * feat(frontend): admin ui changes * refactor: standardize default a link styling (#2719) --------- Co-authored-by: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> --- packages/frontend/app/components/Sidebar.tsx | 12 +-- packages/frontend/app/components/ui/Input.tsx | 6 +- .../app/components/ui/PasswordInput.tsx | 8 +- .../frontend/app/components/ui/Select.tsx | 8 +- .../payments.incoming.$incomingPaymentId.tsx | 2 +- .../payments.outgoing.$outgoingPaymentId.tsx | 7 +- .../frontend/app/routes/peers.$peerId.tsx | 69 ++++++++++++++++ packages/frontend/app/routes/peers.create.tsx | 81 +++++++++++++++++++ ...hooks.data.tsx => webhook-events.data.tsx} | 2 +- .../{webhooks.tsx => webhook-events.tsx} | 6 +- packages/frontend/app/styles/tailwind.css | 5 ++ 11 files changed, 186 insertions(+), 20 deletions(-) rename packages/frontend/app/routes/{webhooks.data.tsx => webhook-events.data.tsx} (97%) rename packages/frontend/app/routes/{webhooks.tsx => webhook-events.tsx} (96%) diff --git a/packages/frontend/app/components/Sidebar.tsx b/packages/frontend/app/components/Sidebar.tsx index 1e14ae4b02..2138f46ef8 100644 --- a/packages/frontend/app/components/Sidebar.tsx +++ b/packages/frontend/app/components/Sidebar.tsx @@ -15,21 +15,21 @@ const navigation = [ name: 'Home', href: '/' }, - { - name: 'Peers', - href: '/peers' - }, { name: 'Assets', href: '/assets' }, + { + name: 'Peers', + href: '/peers' + }, { name: 'Wallet Addresses', href: '/wallet-addresses' }, { - name: 'Webhooks', - href: '/webhooks' + name: 'Webhook Events', + href: '/webhook-events' }, { name: 'Payments', diff --git a/packages/frontend/app/components/ui/Input.tsx b/packages/frontend/app/components/ui/Input.tsx index b2d6f50e1a..0621dc1364 100644 --- a/packages/frontend/app/components/ui/Input.tsx +++ b/packages/frontend/app/components/ui/Input.tsx @@ -8,10 +8,11 @@ type InputProps = Omit, 'className'> & { label?: string error?: string | string[] addOn?: ReactNode + description?: ReactNode } export const Input = forwardRef( - ({ addOn, label, type, error, id, ...props }, ref) => { + ({ description, addOn, label, type, error, id, ...props }, ref) => { const internalId = id ?? useId() return ( @@ -38,6 +39,9 @@ export const Input = forwardRef( {...props} /> + {description ? ( +
{description}
+ ) : null} ) diff --git a/packages/frontend/app/components/ui/PasswordInput.tsx b/packages/frontend/app/components/ui/PasswordInput.tsx index 564b63011d..ab669199ff 100644 --- a/packages/frontend/app/components/ui/PasswordInput.tsx +++ b/packages/frontend/app/components/ui/PasswordInput.tsx @@ -1,4 +1,4 @@ -import type { ComponentPropsWithoutRef } from 'react' +import type { ComponentPropsWithoutRef, ReactNode } from 'react' import { forwardRef, useId, useState } from 'react' import { Eye, EyeSlash } from '../icons' import { FieldError } from './FieldError' @@ -10,10 +10,11 @@ type InputProps = Omit< > & { label?: string error?: string | string[] + description?: ReactNode } export const PasswordInput = forwardRef( - ({ label, error, ...props }, ref) => { + ({ label, error, description, ...props }, ref) => { const id = useId() const [isVisible, setIsVisible] = useState(false) @@ -45,6 +46,9 @@ export const PasswordInput = forwardRef( )} + {description ? ( +
{description}
+ ) : null} ) diff --git a/packages/frontend/app/components/ui/Select.tsx b/packages/frontend/app/components/ui/Select.tsx index f203e18d44..70581ec82e 100644 --- a/packages/frontend/app/components/ui/Select.tsx +++ b/packages/frontend/app/components/ui/Select.tsx @@ -1,3 +1,4 @@ +import type { ReactNode } from 'react' import { Fragment, useId, useState } from 'react' import { Combobox, Transition } from '@headlessui/react' import { Input } from './Input' @@ -19,6 +20,7 @@ type SelectProps = { required?: boolean error?: string | string[] defaultValue?: SelectOption + description?: ReactNode } export const Select = ({ @@ -32,7 +34,8 @@ export const Select = ({ defaultValue = { label: '', value: '' - } + }, + description }: SelectProps) => { const id = useId() const [internalValue, setInternalValue] = useState(defaultValue) @@ -82,6 +85,9 @@ export const Select = ({ )} + {description ? ( +
{description}
+ ) : null} {error ? : null} Wallet Address ID

{incomingPayment.walletAddressId} diff --git a/packages/frontend/app/routes/payments.outgoing.$outgoingPaymentId.tsx b/packages/frontend/app/routes/payments.outgoing.$outgoingPaymentId.tsx index e7b07c5c92..a2686b5f08 100644 --- a/packages/frontend/app/routes/payments.outgoing.$outgoingPaymentId.tsx +++ b/packages/frontend/app/routes/payments.outgoing.$outgoingPaymentId.tsx @@ -86,7 +86,7 @@ export default function ViewOutgoingPaymentPage() {

Wallet Address ID

{outgoingPayment.walletAddressId} @@ -99,10 +99,7 @@ export default function ViewOutgoingPaymentPage() {

Receiver

- + {outgoingPayment.receiver}
diff --git a/packages/frontend/app/routes/peers.$peerId.tsx b/packages/frontend/app/routes/peers.$peerId.tsx index fc2eb716c7..71497ca386 100644 --- a/packages/frontend/app/routes/peers.$peerId.tsx +++ b/packages/frontend/app/routes/peers.$peerId.tsx @@ -121,6 +121,18 @@ export default function ViewPeerPage() { defaultValue={peer.name ?? ''} placeholder='Peer name' error={response?.errors.general.fieldErrors.name} + description={ + <> + The name of the{' '} + + peer + + . + + } /> + {"The peer's "} + + address on the Interledger network. + + + } /> + The maximum amount of value that can be sent in a single{' '} + + Interledger STREAM Packet + + . + + } />
@@ -174,6 +209,17 @@ export default function ViewPeerPage() { label='Incoming Auth Tokens' placeholder='Accepts a comma separated list of tokens' error={response?.errors.http.fieldErrors.incomingAuthTokens} + description={ + <> + List of valid tokens to accept when receiving{' '} + + incoming ILP packets from the peer. + + + } /> + List of valid tokens to present when sending{' '} + + outgoing ILP packets to the peer. + + + } /> + Endpoint on the peer to which{' '} + + outgoing ILP packets + {' '} + will be sent. + + } />
diff --git a/packages/frontend/app/routes/peers.create.tsx b/packages/frontend/app/routes/peers.create.tsx index a48529e93f..c76d4b90ff 100644 --- a/packages/frontend/app/routes/peers.create.tsx +++ b/packages/frontend/app/routes/peers.create.tsx @@ -59,6 +59,18 @@ export default function CreatePeerPage() { label='Name' placeholder='Peer name' error={response?.errors?.fieldErrors.name} + description={ + <> + The name of the{' '} + + peer + {' '} + to be added. + + } /> + {"The peer's "} + + address on the Interledger network. + + + } /> + The maximum amount of value that can be sent in a single{' '} + + Interledger STREAM Packet + + . + + } />
@@ -89,6 +124,17 @@ export default function CreatePeerPage() { label='Incoming Auth Tokens' placeholder='Accepts a comma separated list of tokens' error={response?.errors?.fieldErrors?.incomingAuthTokens} + description={ + <> + List of valid tokens to accept when receiving{' '} + + incoming ILP packets from the peer. + + + } /> + List of valid tokens to present when sending{' '} + + outgoing ILP packets to the peer. + + + } /> + Endpoint on the peer to which{' '} + + outgoing ILP packets + {' '} + will be sent. + + } /> @@ -124,6 +193,18 @@ export default function CreatePeerPage() { name='asset' placeholder='Select asset...' label='Asset' + description={ + <> + The type of{' '} + + asset + {' '} + that is sent to & received from the peer. + + } required /> diff --git a/packages/frontend/app/routes/webhooks.data.tsx b/packages/frontend/app/routes/webhook-events.data.tsx similarity index 97% rename from packages/frontend/app/routes/webhooks.data.tsx rename to packages/frontend/app/routes/webhook-events.data.tsx index cc17ae16a8..aa441a899b 100644 --- a/packages/frontend/app/routes/webhooks.data.tsx +++ b/packages/frontend/app/routes/webhook-events.data.tsx @@ -18,7 +18,7 @@ export default function WebhookEventData() { const [searchParams] = useSearchParams() const state = location.state as { data: string } const dismiss = () => - navigate(`/webhooks${searchParams ? `?${searchParams}` : null}`, { + navigate(`/webhook-events${searchParams ? `?${searchParams}` : null}`, { preventScrollReset: true }) diff --git a/packages/frontend/app/routes/webhooks.tsx b/packages/frontend/app/routes/webhook-events.tsx similarity index 96% rename from packages/frontend/app/routes/webhooks.tsx rename to packages/frontend/app/routes/webhook-events.tsx index fc41729739..347089fb46 100644 --- a/packages/frontend/app/routes/webhooks.tsx +++ b/packages/frontend/app/routes/webhook-events.tsx @@ -42,14 +42,14 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { const previousPageSearchParams = new URLSearchParams() previousPageSearchParams.set('before', webhooks.pageInfo.startCursor) if (type.length > 0) previousPageSearchParams.set('type', type.join(',')) - previousPageUrl = `/webhooks?${previousPageSearchParams.toString()}` + previousPageUrl = `/webhook-events?${previousPageSearchParams.toString()}` } if (webhooks.pageInfo.hasNextPage && webhooks.pageInfo.endCursor) { const nextPageSearchParams = new URLSearchParams() nextPageSearchParams.set('after', webhooks.pageInfo.endCursor) if (type.length > 0) nextPageSearchParams.set('type', type.join(',')) - nextPageUrl = `/webhooks?${nextPageSearchParams.toString()}` + nextPageUrl = `/webhook-events?${nextPageSearchParams.toString()}` } return json({ webhooks, previousPageUrl, nextPageUrl, type }) @@ -133,7 +133,7 @@ export default function WebhookEventsPage() {