Initial frontend for gRPC UI

This commit is contained in:
Gregory Schier
2024-01-30 16:43:54 -08:00
parent c51d5c5377
commit c64f1108f0
16 changed files with 650 additions and 132 deletions

View File

@@ -1,43 +1,36 @@
import type { EditorView } from 'codemirror';
import type { FormEvent } from 'react';
import { memo, useCallback, useRef, useState } from 'react';
import { memo, useRef, useState } from 'react';
import { useHotKey } from '../hooks/useHotKey';
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { useSendRequest } from '../hooks/useSendRequest';
import { useUpdateRequest } from '../hooks/useUpdateRequest';
import type { HttpRequest } from '../lib/models';
import { IconButton } from './core/IconButton';
import { Input } from './core/Input';
import { RequestMethodDropdown } from './RequestMethodDropdown';
type Props = Pick<HttpRequest, 'id' | 'url' | 'method'> & {
type Props = Pick<HttpRequest, 'id' | 'url'> & {
className?: string;
method: HttpRequest['method'] | null;
placeholder: string;
onSubmit: (e: FormEvent) => void;
onUrlChange: (url: string) => void;
onMethodChange?: (method: string) => void;
isLoading: boolean;
forceUpdateKey: string;
};
export const UrlBar = memo(function UrlBar({ id: requestId, url, method, className }: Props) {
export const UrlBar = memo(function UrlBar({
forceUpdateKey,
onUrlChange,
url,
method,
placeholder,
className,
onSubmit,
onMethodChange,
isLoading,
}: Props) {
const inputRef = useRef<EditorView>(null);
const sendRequest = useSendRequest(requestId);
const updateRequest = useUpdateRequest(requestId);
const [isFocused, setIsFocused] = useState<boolean>(false);
const handleMethodChange = useCallback(
(method: string) => updateRequest.mutate({ method }),
[updateRequest],
);
const handleUrlChange = useCallback(
(url: string) => updateRequest.mutate({ url }),
[updateRequest],
);
const loading = useIsResponseLoading(requestId);
const { updateKey } = useRequestUpdateKey(requestId);
const handleSubmit = useCallback(
async (e: FormEvent) => {
e.preventDefault();
sendRequest.mutate();
},
[sendRequest],
);
useHotKey('urlBar.focus', () => {
const head = inputRef.current?.state.doc.length ?? 0;
@@ -48,7 +41,7 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
});
return (
<form onSubmit={handleSubmit} className={className}>
<form onSubmit={onSubmit} className={className}>
<Input
autocompleteVariables
ref={inputRef}
@@ -60,19 +53,22 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
className="px-0 py-0.5"
name="url"
label="Enter URL"
forceUpdateKey={updateKey}
forceUpdateKey={forceUpdateKey}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
containerClassName="shadow shadow-gray-100 dark:shadow-gray-50"
onChange={handleUrlChange}
onChange={onUrlChange}
defaultValue={url}
placeholder="https://example.com"
placeholder={placeholder}
leftSlot={
<RequestMethodDropdown
method={method}
onChange={handleMethodChange}
className="mx-0.5 my-0.5"
/>
method != null &&
onMethodChange != null && (
<RequestMethodDropdown
method={method}
onChange={onMethodChange}
className="mx-0.5 my-0.5"
/>
)
}
rightSlot={
<IconButton
@@ -81,8 +77,8 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
title="Send Request"
type="submit"
className="w-8 mr-0.5 my-0.5"
icon={loading ? 'update' : 'sendHorizontal'}
spin={loading}
icon={isLoading ? 'update' : 'sendHorizontal'}
spin={isLoading}
hotkeyAction="request.send"
/>
}