Skip to content

Commit

Permalink
fix: replace headlessui components and cleanup lower screens
Browse files Browse the repository at this point in the history
  • Loading branch information
davemooreuws committed Apr 2, 2024
1 parent 2f8d903 commit 655e7ed
Show file tree
Hide file tree
Showing 13 changed files with 681 additions and 740 deletions.
62 changes: 39 additions & 23 deletions pkg/dashboard/frontend/src/components/apis/APIExplorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {
LocalStorageHistoryItem,
} from '../../types'
import {
Select,
Badge,
Spinner,
Tabs,
Expand Down Expand Up @@ -43,6 +42,15 @@ import { APIMethodBadge } from './APIMethodBadge'
import { Button } from '../ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip'
import BreadCrumbs from '../layout/BreadCrumbs'
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from '../ui/select'

const getTabCount = (rows: FieldRow[]) => {
if (!rows) return 0
Expand Down Expand Up @@ -391,26 +399,34 @@ const APIExplorer = () => {
/>
</div>
<div className="lg:hidden">
<Select<Endpoint>
items={paths}
label="Endpoint"
id="endpoint-select"
className="w-full"
selected={selectedApiEndpoint}
setSelected={setSelectedApiEndpoint}
display={(v) => (
<div className="grid grid-cols-12 items-center gap-4 p-0.5 text-lg">
<APIMethodBadge
method={v.method}
className="col-span-3 w-20 px-1 !text-lg md:col-span-2"
/>
<div className="col-span-9 flex gap-4 md:col-span-10">
<span>{v?.api}</span>
<span>{v?.path}</span>
</div>
</div>
)}
/>
<Select
value={selectedApiEndpoint.id}
onValueChange={(id) => {
setSelectedApiEndpoint(paths.find((p) => p.id === id))
}}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select Endpoint" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{paths.map((path) => (
<SelectItem key={path.id} value={path.id}>
<div className="grid grid-cols-12 items-center gap-4 p-0.5 text-lg">
<APIMethodBadge
method={path.method}
className="col-span-3 w-20 px-1.5 !text-lg md:col-span-2"
/>
<div className="col-span-9 flex gap-4 md:col-span-10">
<span>{path?.api}</span>
<span>{path?.path}</span>
</div>
</div>
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>

<div className="flex items-center gap-4">
Expand Down Expand Up @@ -472,7 +488,7 @@ const APIExplorer = () => {
</div>
</div>

<div className="bg-white shadow sm:rounded-lg">
<div className="rounded-lg bg-white shadow">
<Tabs
tabs={tabs}
index={currentTabIndex}
Expand Down Expand Up @@ -581,7 +597,7 @@ const APIExplorer = () => {
</div>
</div>
</div>
<div className="bg-white shadow sm:rounded-lg">
<div className="rounded-lg bg-white shadow">
<div className="px-4 py-5 sm:p-6">
<div className="sm:flex sm:items-start sm:justify-between">
<div className="relative w-full">
Expand Down
202 changes: 82 additions & 120 deletions pkg/dashboard/frontend/src/components/apis/APIHistory.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { ApiHistoryItem, Endpoint } from '../../types'
import Badge from '../shared/Badge'
import { formatJSON, getDateString } from '../../lib/utils'
import { Disclosure } from '@headlessui/react'
import { ChevronUpIcon } from '@heroicons/react/20/solid'
import type { ApiHistoryItem } from '../../types'
import { formatJSON } from '../../lib/utils'
import { useState } from 'react'
import { Tabs } from '../shared'
import CodeEditor from './CodeEditor'
import APIResponseContent from './APIResponseContent'
import TableGroup from '../shared/TableGroup'
import { ScrollArea } from '../ui/scroll-area'
import HistoryAccordion from '../shared/HistoryAccordion'

interface Props {
history: ApiHistoryItem[]
Expand Down Expand Up @@ -45,13 +42,14 @@ const APIHistory: React.FC<Props> = ({ history, selectedRequest }) => {
}

return (
<ScrollArea className="h-[30rem]" type="always">
<div className="flex flex-col gap-2">
{requestHistory.map((h, idx) => (
<ApiHistoryAccordion key={idx} {...h} />
))}
</div>
</ScrollArea>
<HistoryAccordion
items={requestHistory.map((h) => ({
label: h.event.api + h.event.request.path,
time: h.time,
status: h.event?.response?.status,
content: <ApiHistoryAccordionContent {...h} />,
}))}
/>
)
}

Expand All @@ -65,9 +63,8 @@ function isJSON(data: string | undefined) {
return true
}

const ApiHistoryAccordion: React.FC<ApiHistoryItem> = ({
time,
event: { api, request, response },
const ApiHistoryAccordionContent: React.FC<ApiHistoryItem> = ({
event: { request, response },
}) => {
const [tabIndex, setTabIndex] = useState(0)

Expand All @@ -78,116 +75,81 @@ const ApiHistoryAccordion: React.FC<ApiHistoryItem> = ({
const jsonTabs = [...tabs, { name: 'Payload' }]

return (
<Disclosure>
{({ open }) => (
<>
<Disclosure.Button className="flex w-full justify-between rounded-lg border border-slate-100 bg-white px-4 py-2 text-left text-sm font-medium text-black hover:bg-blue-100 focus:outline-none focus-visible:ring focus-visible:ring-blue-500 focus-visible:ring-opacity-75">
<div className="flex w-full flex-row justify-between">
<div className="flex flex-row gap-4">
{response.status && (
<Badge
status={response.status < 400 ? 'green' : 'red'}
className="!text-md h-6 w-12 sm:w-20"
>
<span className="mr-0.5 hidden md:inline">Status: </span>
{response.status}
</Badge>
)}
<p className="max-w-[200px] truncate md:max-w-lg">
{api}
{request.path}
</p>
</div>
<div className="flex flex-row gap-2 md:gap-4">
<p className="hidden sm:inline">{getDateString(time)}</p>
<ChevronUpIcon
className={`${
open ? 'rotate-180 transform' : ''
} h-5 w-5 text-blue-500`}
<div className="flex flex-col py-4">
<div className="bg-white sm:rounded-lg">
<Tabs
tabs={isJson ? jsonTabs : tabs}
index={tabIndex}
setIndex={setTabIndex}
/>
<div className="py-5">
{tabIndex === 0 && (
<TableGroup
headers={['Key', 'Value']}
rowDataClassName="max-w-[100px]"
groups={[
{
name: 'Request Headers',
rows: Object.entries(request.headers)
.filter(([key, value]) => key && value)
.map(([key, value]) => [
key.toLowerCase(),
value.join(', '),
]),
},
{
name: 'Response Headers',
rows: Object.entries(response.headers ?? [])
.filter(([key, value]) => key && value)
.map(([key, value]) => [key.toLowerCase(), value]),
},
]}
/>
)}
{tabIndex === 1 && (
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<p className="text-md font-semibold">Response Data</p>
<APIResponseContent
response={{ ...response, data: atob(response.data) }}
/>
</div>
</div>
</Disclosure.Button>
<Disclosure.Panel className="pb-2 text-sm text-gray-500">
<div className="flex flex-col py-4">
<div className="bg-white shadow sm:rounded-lg">
<Tabs
tabs={isJson ? jsonTabs : tabs}
index={tabIndex}
setIndex={setTabIndex}
/>
<div className="py-5">
{tabIndex === 0 && (
<TableGroup
headers={['Key', 'Value']}
rowDataClassName="max-w-[100px]"
groups={[
{
name: 'Request Headers',
rows: Object.entries(request.headers)
.filter(([key, value]) => key && value)
.map(([key, value]) => [
key.toLowerCase(),
value.join(', '),
]),
},
{
name: 'Response Headers',
rows: Object.entries(response.headers ?? [])
.filter(([key, value]) => key && value)
.map(([key, value]) => [key.toLowerCase(), value]),
},
]}
/>
)}
{tabIndex === 1 && (
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<p className="text-md font-semibold">Response Data</p>
<APIResponseContent
response={{ ...response, data: atob(response.data) }}
/>
</div>
</div>
)}
{tabIndex === 2 && (
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<p className="text-md font-semibold">Request Body</p>
<CodeEditor
contentType="application/json"
readOnly={true}
value={formatJSON(
JSON.parse(atob(request.body?.toString() ?? '')),
)}
{tabIndex === 2 && (
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<p className="text-md font-semibold">Request Body</p>
<CodeEditor
contentType="application/json"
readOnly={true}
value={formatJSON(
JSON.parse(atob(request.body?.toString() ?? '')),
)}
title="Request Body"
/>
</div>
<div className="flex flex-col gap-2">
{request.queryParams && (
<TableGroup
headers={['Key', 'Value']}
rowDataClassName="max-w-[100px]"
groups={[
{
name: 'Query Params',
rows: request.queryParams
.filter(({ key, value }) => key && value)
.map(({ key, value }) => [key, value]),
},
]}
/>
)}
</div>
</div>
)}
</div>
title="Request Body"
/>
</div>
<div className="flex flex-col gap-2">
{request.queryParams && (
<TableGroup
headers={['Key', 'Value']}
rowDataClassName="max-w-[100px]"
groups={[
{
name: 'Query Params',
rows: request.queryParams
.filter(({ key, value }) => key && value)
.map(({ key, value }) => [key, value]),
},
]}
/>
)}
</div>
</div>
</Disclosure.Panel>
</>
)}
</Disclosure>
)}
</div>
</div>
</div>
)
}

Expand Down
Loading

0 comments on commit 655e7ed

Please sign in to comment.