mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 01:28:35 +02: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 "
|
"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": {
|
"448a1d1f1866ab42c0f81fcf8eb2930bf21dfdd43ca4831bc1a198cf45ac3732": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
@@ -322,6 +312,16 @@
|
|||||||
},
|
},
|
||||||
"query": "\n SELECT id, created_at, updated_at, deleted_at, name, description\n FROM workspaces\n "
|
"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": {
|
"a83698dcf9a815b881097133edb31a34ba25e7c6c114d463c495342a85371639": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
|||||||
@@ -110,6 +110,16 @@ async fn send_request(
|
|||||||
HeaderValue::from_str(models::generate_id("x").as_str()).expect("Failed to create header"),
|
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 =
|
let m =
|
||||||
Method::from_bytes(req.method.to_uppercase().as_bytes()).expect("Failed to create method");
|
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);
|
let builder = client.request(m, url_string.to_string()).headers(headers);
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ pub async fn upsert_request(
|
|||||||
updated_at = CURRENT_TIMESTAMP,
|
updated_at = CURRENT_TIMESTAMP,
|
||||||
name = excluded.name,
|
name = excluded.name,
|
||||||
method = excluded.method,
|
method = excluded.method,
|
||||||
|
headers = excluded.headers,
|
||||||
body = excluded.body,
|
body = excluded.body,
|
||||||
url = excluded.url
|
url = excluded.url
|
||||||
"#,
|
"#,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function App({ matches }: { path: string; matches?: Params }) {
|
|||||||
const isH = screenWidth > 900;
|
const isH = screenWidth > 900;
|
||||||
|
|
||||||
return (
|
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
|
<Sidebar
|
||||||
requests={requests ?? []}
|
requests={requests ?? []}
|
||||||
workspaceId={workspaceId}
|
workspaceId={workspaceId}
|
||||||
|
|||||||
@@ -1,24 +1,35 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
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 { IconButton } from './IconButton';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
import { VStack } from './Stacks';
|
import { VStack } from './Stacks';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
request: HttpRequest;
|
||||||
|
}
|
||||||
|
|
||||||
type PairWithId = { header: Partial<HttpHeader>; id: string };
|
type PairWithId = { header: Partial<HttpHeader>; id: string };
|
||||||
|
|
||||||
export function HeaderEditor() {
|
export function HeaderEditor({ request }: Props) {
|
||||||
|
const updateRequest = useRequestUpdate(request);
|
||||||
const newPair = () => {
|
const newPair = () => {
|
||||||
return { header: { name: '', value: '' }, id: Math.random().toString() };
|
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) => {
|
const handleChangeHeader = (pair: PairWithId) => {
|
||||||
setPairs((pairs) =>
|
setPairs((pairs) => {
|
||||||
pairs.map((p) =>
|
const newPairs = pairs.map((p) =>
|
||||||
pair.id !== p.id ? p : { id: p.id, header: { ...p.header, ...pair.header } },
|
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(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export function RequestPane({ fullHeight, request, className }: Props) {
|
|||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="headers" className="pl-2">
|
<TabContent value="headers" className="pl-2">
|
||||||
<HeaderEditor />
|
<HeaderEditor key={request.id} request={request} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</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 { ScrollArea } from './ScrollArea';
|
||||||
import { HStack } from './Stacks';
|
import { HStack } from './Stacks';
|
||||||
|
|
||||||
|
import './Tabs.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -49,9 +51,12 @@ export function TabTrigger({ value, children, active }: TabTriggerProps) {
|
|||||||
return (
|
return (
|
||||||
<T.Trigger value={value} asChild>
|
<T.Trigger value={value} asChild>
|
||||||
<Button
|
<Button
|
||||||
|
color="custom"
|
||||||
size="sm"
|
size="sm"
|
||||||
disabled={active}
|
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}
|
{children}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -67,7 +72,11 @@ interface TabContentProps {
|
|||||||
|
|
||||||
export function TabContent({ value, children, className }: TabContentProps) {
|
export function TabContent({ value, children, className }: TabContentProps) {
|
||||||
return (
|
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}
|
{children}
|
||||||
</T.Content>
|
</T.Content>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user