Hook up header editor!

This commit is contained in:
Gregory Schier
2023-03-09 13:07:13 -08:00
parent 109006db66
commit de0bd57622
9 changed files with 57 additions and 21 deletions

Binary file not shown.

View File

@@ -92,16 +92,6 @@
},
"query": "\n SELECT id, workspace_id, created_at, updated_at, deleted_at, name, url, method, body,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpRequestHeader>>\"\n FROM http_requests\n WHERE workspace_id = ?\n "
},
"3d3cc959cd3844950dde2426945bad638fa5f1a46c4681b5fe2bff60780dea62": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 7
}
},
"query": "\n INSERT INTO http_requests (id, workspace_id, name, url, method, body, headers, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n method = excluded.method,\n body = excluded.body,\n url = excluded.url\n "
},
"448a1d1f1866ab42c0f81fcf8eb2930bf21dfdd43ca4831bc1a198cf45ac3732": {
"describe": {
"columns": [],
@@ -322,6 +312,16 @@
},
"query": "\n SELECT id, created_at, updated_at, deleted_at, name, description\n FROM workspaces\n "
},
"a097740ea4ab772ec6f9d8a5144d6871e0b172130d5abe4da61e663155d2bf25": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 7
}
},
"query": "\n INSERT INTO http_requests (id, workspace_id, name, url, method, body, headers, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n method = excluded.method,\n headers = excluded.headers,\n body = excluded.body,\n url = excluded.url\n "
},
"a83698dcf9a815b881097133edb31a34ba25e7c6c114d463c495342a85371639": {
"describe": {
"columns": [],

View File

@@ -110,6 +110,16 @@ async fn send_request(
HeaderValue::from_str(models::generate_id("x").as_str()).expect("Failed to create header"),
);
for h in req.headers.0 {
if h.name.is_empty() {
continue;
}
headers.insert(
HeaderName::from_bytes(h.name.as_bytes()).expect("Failed to create header name"),
HeaderValue::from_str(h.value.as_str()).expect("Failed to create header value"),
);
}
let m =
Method::from_bytes(req.method.to_uppercase().as_bytes()).expect("Failed to create method");
let builder = client.request(m, url_string.to_string()).headers(headers);

View File

@@ -137,6 +137,7 @@ pub async fn upsert_request(
updated_at = CURRENT_TIMESTAMP,
name = excluded.name,
method = excluded.method,
headers = excluded.headers,
body = excluded.body,
url = excluded.url
"#,

View File

@@ -24,7 +24,7 @@ export function App({ matches }: { path: string; matches?: Params }) {
const isH = screenWidth > 900;
return (
<div className="grid grid-cols-[auto_1fr] h-full text-gray-900 overflow-hidden rounded-[11px]">
<div className="grid grid-cols-[auto_1fr] h-full text-gray-900 overflow-hidden">
<Sidebar
requests={requests ?? []}
workspaceId={workspaceId}

View File

@@ -1,24 +1,35 @@
import React, { useEffect, useState } from 'react';
import type { HttpHeader } from '../lib/models';
import { useRequestUpdate } from '../hooks/useRequest';
import type { HttpHeader, HttpRequest } from '../lib/models';
import { IconButton } from './IconButton';
import { Input } from './Input';
import { VStack } from './Stacks';
interface Props {
request: HttpRequest;
}
type PairWithId = { header: Partial<HttpHeader>; id: string };
export function HeaderEditor() {
export function HeaderEditor({ request }: Props) {
const updateRequest = useRequestUpdate(request);
const newPair = () => {
return { header: { name: '', value: '' }, id: Math.random().toString() };
};
const [pairs, setPairs] = useState<PairWithId[]>([newPair()]);
const [pairs, setPairs] = useState<PairWithId[]>(
request.headers.map((h) => ({ header: h, id: Math.random().toString() })),
);
const handleChangeHeader = (pair: PairWithId) => {
setPairs((pairs) =>
pairs.map((p) =>
setPairs((pairs) => {
const newPairs = pairs.map((p) =>
pair.id !== p.id ? p : { id: p.id, header: { ...p.header, ...pair.header } },
),
);
);
const headers = newPairs.map((p) => ({ name: '', value: '', ...p.header }));
updateRequest.mutate({ headers });
return newPairs;
});
};
useEffect(() => {

View File

@@ -54,7 +54,7 @@ export function RequestPane({ fullHeight, request, className }: Props) {
/>
</TabContent>
<TabContent value="headers" className="pl-2">
<HeaderEditor />
<HeaderEditor key={request.id} request={request} />
</TabContent>
</Tabs>
</div>

View File

@@ -0,0 +1,5 @@
.tab-content {
&[data-state="inactive"] {
@apply hidden;
}
}

View File

@@ -6,6 +6,8 @@ import { Button } from './Button';
import { ScrollArea } from './ScrollArea';
import { HStack } from './Stacks';
import './Tabs.css';
interface Props {
defaultValue?: string;
label: string;
@@ -49,9 +51,12 @@ export function TabTrigger({ value, children, active }: TabTriggerProps) {
return (
<T.Trigger value={value} asChild>
<Button
color="custom"
size="sm"
disabled={active}
className={classnames(active ? 'bg-gray-100' : '!text-gray-500 hover:!text-gray-800')}
className={classnames(
active ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900',
)}
>
{children}
</Button>
@@ -67,7 +72,11 @@ interface TabContentProps {
export function TabContent({ value, children, className }: TabContentProps) {
return (
<T.Content value={value} className={classnames(className, 'w-full h-full')}>
<T.Content
forceMount
value={value}
className={classnames(className, 'tab-content', 'w-full h-full')}
>
{children}
</T.Content>
);