mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-17 23:13:51 +01:00
Hook up header editor!
This commit is contained in:
Binary file not shown.
@@ -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": [],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
"#,
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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>
|
||||
|
||||
5
src-web/components/Tabs.css
Normal file
5
src-web/components/Tabs.css
Normal file
@@ -0,0 +1,5 @@
|
||||
.tab-content {
|
||||
&[data-state="inactive"] {
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user