mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-18 23:44:12 +01:00
Better response headers
This commit is contained in:
@@ -5,5 +5,9 @@ interface Props {
|
||||
}
|
||||
|
||||
export function EmptyStateText({ children }: Props) {
|
||||
return <div className="h-full text-gray-400 flex items-center justify-center">{children}</div>;
|
||||
return (
|
||||
<div className="rounded-lg border border-dashed border-highlight h-full text-gray-400 flex items-center justify-center">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,9 +96,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
|
||||
label: (
|
||||
<div className="flex items-center">
|
||||
Headers
|
||||
<CountBadge
|
||||
count={activeRequest.headers.filter((h) => h.name && h.value).length}
|
||||
/>
|
||||
<CountBadge count={activeRequest.headers.filter((h) => h.name).length} />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@@ -164,7 +162,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
|
||||
label="Request"
|
||||
onChangeValue={setActiveTab}
|
||||
tabs={tabs}
|
||||
className="mt-1"
|
||||
tabListClassName="mt-2"
|
||||
>
|
||||
<TabContent value="auth">
|
||||
{activeRequest.authenticationType === AUTH_TYPE_BASIC ? (
|
||||
@@ -199,7 +197,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
|
||||
onChange={() => null}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent value="body" className="mt-1">
|
||||
<TabContent value="body">
|
||||
{activeRequest.bodyType === BODY_TYPE_JSON ? (
|
||||
<Editor
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
|
||||
26
src-web/components/ResponseHeaders.tsx
Normal file
26
src-web/components/ResponseHeaders.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import classnames from 'classnames';
|
||||
import type { HttpResponse } from '../lib/models';
|
||||
import { HStack } from './core/Stacks';
|
||||
|
||||
interface Props {
|
||||
headers: HttpResponse['headers'];
|
||||
}
|
||||
|
||||
export function ResponseHeaders({ headers }: Props) {
|
||||
return (
|
||||
<dl className="font-mono text-xs table-fixed w-full">
|
||||
{headers.map((h, i) => {
|
||||
return (
|
||||
<HStack
|
||||
space={3}
|
||||
key={i}
|
||||
className={classnames(i > 0 && 'border-t border-highlightSecondary', 'py-1')}
|
||||
>
|
||||
<dd className="w-1/3 text-violet-600 select-text cursor-text">{h.name}</dd>
|
||||
<dt className="w-2/3 text-blue-600 select-text cursor-text break-all">{h.value}</dt>
|
||||
</HStack>
|
||||
);
|
||||
})}
|
||||
</dl>
|
||||
);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import { StatusColor } from './core/StatusColor';
|
||||
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
||||
import { Webview } from './core/Webview';
|
||||
import { EmptyStateText } from './EmptyStateText';
|
||||
import { ResponseHeaders } from './ResponseHeaders';
|
||||
|
||||
interface Props {
|
||||
style?: CSSProperties;
|
||||
@@ -81,7 +82,11 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
||||
>
|
||||
<HStack
|
||||
alignItems="center"
|
||||
className="italic text-gray-700 text-sm w-full flex-shrink-0 -mb-1"
|
||||
className={classnames(
|
||||
'italic text-gray-700 text-sm w-full flex-shrink-0',
|
||||
// Remove a bit of space because the tabs have lots too
|
||||
'-mb-1.5',
|
||||
)}
|
||||
>
|
||||
{activeResponse && (
|
||||
<>
|
||||
@@ -171,14 +176,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
||||
) : null}
|
||||
</TabContent>
|
||||
<TabContent value="headers">
|
||||
<ul>
|
||||
{activeResponse?.headers.map((h) => (
|
||||
<li key={h.name} className="font-mono text-xs">
|
||||
<span className="text-violet-600 select-text cursor-text">{h.name}</span>:{' '}
|
||||
<span className="text-blue-600 select-text cursor-text">{h.value}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<ResponseHeaders headers={activeResponse?.headers ?? []} />
|
||||
</TabContent>
|
||||
</Tabs>
|
||||
)}
|
||||
|
||||
@@ -5,8 +5,10 @@ interface Props {
|
||||
export function CountBadge({ count }: Props) {
|
||||
if (count === 0) return null;
|
||||
return (
|
||||
<div aria-hidden className="opacity-80 text-2xs border rounded px-1 mb-0.5 ml-1 h-4">
|
||||
{count}
|
||||
</div>
|
||||
<>
|
||||
<div aria-hidden className="opacity-70 text-3xs rounded mb-0.5 ml-1 h-4 font-mono">
|
||||
{count}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -117,13 +117,12 @@ export const PairEditor = memo(function PairEditor({
|
||||
);
|
||||
|
||||
const handleFocus = useCallback(
|
||||
(pair: PairContainer) => {
|
||||
const isLast = pair.id === pairs[pairs.length - 1]?.id;
|
||||
if (isLast) {
|
||||
setPairs((pairs) => [...pairs, newPairContainer()]);
|
||||
}
|
||||
},
|
||||
[pairs],
|
||||
(pair: PairContainer) =>
|
||||
setPairs((pairs) => {
|
||||
const isLast = pair.id === pairs[pairs.length - 1]?.id;
|
||||
return isLast ? [...pairs, newPairContainer()] : pairs;
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
// Ensure there's always at least one pair
|
||||
@@ -138,7 +137,7 @@ export const PairEditor = memo(function PairEditor({
|
||||
className={classnames(
|
||||
className,
|
||||
'@container',
|
||||
'overflow-auto max-h-full pb-2 grid',
|
||||
'pb-2 grid',
|
||||
// Move over the width of the drag handle
|
||||
'-ml-3',
|
||||
)}
|
||||
|
||||
@@ -73,18 +73,15 @@ export function Tabs({
|
||||
aria-label={label}
|
||||
className={classnames(
|
||||
tabListClassName,
|
||||
'h-md flex items-center overflow-x-auto hide-scrollbars',
|
||||
// Give space for button focus states within overflow boundary
|
||||
'flex items-center overflow-x-auto hide-scrollbars mt-1 mb-2',
|
||||
// Give space for button focus states within overflow boundary.
|
||||
'px-2 -mx-2',
|
||||
)}
|
||||
>
|
||||
<HStack space={3} className="-ml-1 flex-shrink-0">
|
||||
<HStack space={1} className="flex-shrink-0">
|
||||
{tabs.map((t) => {
|
||||
const isActive = t.value === value;
|
||||
const btnClassName = classnames(
|
||||
'!px-1',
|
||||
isActive ? 'text-gray-900' : 'text-gray-600 hover:text-gray-800',
|
||||
);
|
||||
const btnClassName = classnames(isActive ? 'bg-highlightSecondary' : 'text-gray-600');
|
||||
if ('options' in t) {
|
||||
const option = t.options.items.find(
|
||||
(i) => 'value' in i && i.value === t.options?.value,
|
||||
@@ -148,7 +145,7 @@ export const TabContent = memo(function TabContent({
|
||||
<div
|
||||
tabIndex={-1}
|
||||
data-tab={value}
|
||||
className={classnames(className, 'tab-content', 'hidden w-full h-full')}
|
||||
className={classnames(className, 'tab-content', 'overflow-auto hidden w-full h-full')}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -32,6 +32,7 @@ module.exports = {
|
||||
"sans": ["Inter", "sans-serif"]
|
||||
},
|
||||
fontSize: {
|
||||
'3xs': "0.6rem",
|
||||
'2xs': "0.7rem",
|
||||
xs: "0.8rem",
|
||||
sm: "0.9rem",
|
||||
|
||||
Reference in New Issue
Block a user