mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-17 23:13:51 +01:00
Markdown documentation for HTTP requests (#145)
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import useResizeObserver from '@react-hook/resize-observer';
|
||||
import useSize from '@react-hook/size';
|
||||
import type { GrpcMetadataEntry, GrpcRequest } from '@yaakapp-internal/models';
|
||||
import classNames from 'classnames';
|
||||
import type { CSSProperties } from 'react';
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { createGlobalState } from 'react-use';
|
||||
import React, { useCallback, useMemo, useRef } from 'react';
|
||||
import { useLocalStorage } from 'react-use';
|
||||
import type { ReflectResponseService } from '../hooks/useGrpc';
|
||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
|
||||
@@ -11,6 +11,7 @@ import { AUTH_TYPE_BASIC, AUTH_TYPE_BEARER, AUTH_TYPE_NONE } from '../lib/model_
|
||||
import { BasicAuth } from './BasicAuth';
|
||||
import { BearerAuth } from './BearerAuth';
|
||||
import { Button } from './core/Button';
|
||||
import { CountBadge } from './core/CountBadge';
|
||||
import { Icon } from './core/Icon';
|
||||
import { IconButton } from './core/IconButton';
|
||||
import { PairOrBulkEditor } from './core/PairOrBulkEditor';
|
||||
@@ -20,6 +21,7 @@ import type { TabItem } from './core/Tabs/Tabs';
|
||||
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
||||
import { EmptyStateText } from './EmptyStateText';
|
||||
import { GrpcEditor } from './GrpcEditor';
|
||||
import { MarkdownEditor } from './MarkdownEditor';
|
||||
import { UrlBar } from './UrlBar';
|
||||
|
||||
interface Props {
|
||||
@@ -44,7 +46,10 @@ interface Props {
|
||||
services: ReflectResponseService[] | null;
|
||||
}
|
||||
|
||||
const useActiveTab = createGlobalState<string>('message');
|
||||
const TAB_MESSAGE = 'message';
|
||||
const TAB_METADATA = 'metadata';
|
||||
const TAB_AUTH = 'auth';
|
||||
const TAB_DESCRIPTION = 'description';
|
||||
|
||||
export function GrpcConnectionSetupPane({
|
||||
style,
|
||||
@@ -61,14 +66,14 @@ export function GrpcConnectionSetupPane({
|
||||
onSend,
|
||||
}: Props) {
|
||||
const updateRequest = useUpdateAnyGrpcRequest();
|
||||
const [activeTab, setActiveTab] = useActiveTab();
|
||||
const [activeTabs, setActiveTabs] = useLocalStorage<Record<string, string>>(
|
||||
'grpcRequestPaneActiveTabs',
|
||||
{},
|
||||
);
|
||||
const { updateKey: forceUpdateKey } = useRequestUpdateKey(activeRequest.id ?? null);
|
||||
|
||||
const [paneSize, setPaneSize] = useState(99999);
|
||||
const urlContainerEl = useRef<HTMLDivElement>(null);
|
||||
useResizeObserver<HTMLDivElement>(urlContainerEl.current, (entry) => {
|
||||
setPaneSize(entry.contentRect.width);
|
||||
});
|
||||
const [paneWidth] = useSize(urlContainerEl.current);
|
||||
|
||||
const handleChangeUrl = useCallback(
|
||||
(url: string) => updateRequest.mutateAsync({ id: activeRequest.id, update: { url } }),
|
||||
@@ -129,9 +134,18 @@ export function GrpcConnectionSetupPane({
|
||||
|
||||
const tabs: TabItem[] = useMemo(
|
||||
() => [
|
||||
{ value: 'message', label: 'Message' },
|
||||
{
|
||||
value: 'auth',
|
||||
value: TAB_DESCRIPTION,
|
||||
label: (
|
||||
<div className="flex items-center">
|
||||
Docs
|
||||
{activeRequest.description && <CountBadge count={true} />}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ value: TAB_MESSAGE, label: 'Message' },
|
||||
{
|
||||
value: TAB_AUTH,
|
||||
label: 'Auth',
|
||||
options: {
|
||||
value: activeRequest.authenticationType,
|
||||
@@ -160,29 +174,44 @@ export function GrpcConnectionSetupPane({
|
||||
},
|
||||
},
|
||||
},
|
||||
{ value: 'metadata', label: 'Metadata' },
|
||||
{ value: TAB_METADATA, label: 'Metadata' },
|
||||
],
|
||||
[
|
||||
activeRequest.authentication,
|
||||
activeRequest.authenticationType,
|
||||
activeRequest.description,
|
||||
activeRequest.id,
|
||||
updateRequest,
|
||||
],
|
||||
);
|
||||
|
||||
const activeTab = activeTabs?.[activeRequest.id];
|
||||
const setActiveTab = useCallback(
|
||||
(tab: string) => {
|
||||
setActiveTabs((r) => ({ ...r, [activeRequest.id]: tab }));
|
||||
},
|
||||
[activeRequest.id, setActiveTabs],
|
||||
);
|
||||
|
||||
const handleMetadataChange = useCallback(
|
||||
(metadata: GrpcMetadataEntry[]) =>
|
||||
updateRequest.mutate({ id: activeRequest.id, update: { metadata } }),
|
||||
[activeRequest.id, updateRequest],
|
||||
);
|
||||
|
||||
const handleDescriptionChange = useCallback(
|
||||
(description: string) =>
|
||||
updateRequest.mutate({ id: activeRequest.id, update: { description } }),
|
||||
[activeRequest.id, updateRequest],
|
||||
);
|
||||
|
||||
return (
|
||||
<VStack style={style}>
|
||||
<div
|
||||
ref={urlContainerEl}
|
||||
className={classNames(
|
||||
'grid grid-cols-[minmax(0,1fr)_auto] gap-1.5',
|
||||
paneSize < 400 && '!grid-cols-1',
|
||||
paneWidth < 400 && '!grid-cols-1',
|
||||
)}
|
||||
>
|
||||
<UrlBar
|
||||
@@ -222,7 +251,7 @@ export function GrpcConnectionSetupPane({
|
||||
disabled={isStreaming || services == null}
|
||||
className={classNames(
|
||||
'font-mono text-editor min-w-[5rem] !ring-0',
|
||||
paneSize < 400 && 'flex-1',
|
||||
paneWidth < 400 && 'flex-1',
|
||||
)}
|
||||
>
|
||||
{select.options.find((o) => o.value === select.value)?.label ?? 'No Schema'}
|
||||
@@ -312,6 +341,14 @@ export function GrpcConnectionSetupPane({
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent value={TAB_DESCRIPTION}>
|
||||
<MarkdownEditor
|
||||
name="request-description"
|
||||
placeholder="A Markdown description of this request."
|
||||
defaultValue={activeRequest.description}
|
||||
onChange={handleDescriptionChange}
|
||||
/>
|
||||
</TabContent>
|
||||
</Tabs>
|
||||
</VStack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user