Fix header editor and scroll in general

This commit is contained in:
Gregory Schier
2023-03-13 19:37:36 -07:00
parent 8be4971a23
commit 4bf22d8a60
13 changed files with 47 additions and 46 deletions

View File

@@ -4,7 +4,8 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri + React + TS</title> <title>Yaak App</title>
<!-- <script src="http://localhost:8097"></script>-->
</head> </head>
<body> <body>

Binary file not shown.

View File

@@ -134,19 +134,6 @@
} }
} }
.cm-scroller, .cm-tooltip-autocomplete > ul {
&::-webkit-scrollbar-corner,
&::-webkit-scrollbar {
@apply w-1.5 h-1.5 bg-transparent;
}
&::-webkit-scrollbar-thumb {
@apply bg-gray-200 hover:bg-gray-300 rounded-full;
}
}
/* <-- */
/* NOTE: Extra selector required to override default styles */ /* NOTE: Extra selector required to override default styles */
.cm-tooltip.cm-tooltip { .cm-tooltip.cm-tooltip {
@apply shadow-lg bg-gray-50 rounded overflow-hidden text-gray-900 border border-gray-200 z-50 pointer-events-auto; @apply shadow-lg bg-gray-50 rounded overflow-hidden text-gray-900 border border-gray-200 z-50 pointer-events-auto;

View File

@@ -5,7 +5,8 @@ import classnames from 'classnames';
import { EditorView } from 'codemirror'; import { EditorView } from 'codemirror';
import { formatSdl } from 'format-graphql'; import { formatSdl } from 'format-graphql';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { useUnmount } from 'react-use'; import { useDebounce, useUnmount } from 'react-use';
import { debounce } from '../../lib/debounce';
import { IconButton } from '../IconButton'; import { IconButton } from '../IconButton';
import './Editor.css'; import './Editor.css';
import { baseExtensions, getLanguageExtension, multiLineExtensions } from './extensions'; import { baseExtensions, getLanguageExtension, multiLineExtensions } from './extensions';
@@ -96,7 +97,7 @@ export function _Editor({
readOnly && 'cm-readonly', readOnly && 'cm-readonly',
)} )}
> >
{contentType?.includes("graphql") && ( {contentType?.includes('graphql') && (
<IconButton <IconButton
icon="eye" icon="eye"
className="absolute right-3 bottom-3 z-10" className="absolute right-3 bottom-3 z-10"

View File

@@ -1,3 +1,4 @@
import classnames from 'classnames';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useRequestUpdate } from '../hooks/useRequest'; import { useRequestUpdate } from '../hooks/useRequest';
import type { HttpHeader, HttpRequest } from '../lib/models'; import type { HttpHeader, HttpRequest } from '../lib/models';
@@ -7,11 +8,12 @@ import { VStack } from './Stacks';
interface Props { interface Props {
request: HttpRequest; request: HttpRequest;
className?: string;
} }
type PairWithId = { header: Partial<HttpHeader>; id: string }; type PairWithId = { header: Partial<HttpHeader>; id: string };
export function HeaderEditor({ request }: Props) { export function HeaderEditor({ request, className }: Props) {
const updateRequest = useRequestUpdate(request); const updateRequest = useRequestUpdate(request);
const saveHeaders = (pairs: PairWithId[]) => { const saveHeaders = (pairs: PairWithId[]) => {
const headers = pairs.map((p) => ({ name: '', value: '', ...p.header })); const headers = pairs.map((p) => ({ name: '', value: '', ...p.header }));
@@ -59,7 +61,7 @@ export function HeaderEditor({ request }: Props) {
}; };
return ( return (
<div className="pb-6"> <div className={classnames(className, 'pb-6 grid')}>
<VStack space={2}> <VStack space={2}>
{pairs.map((p, i) => ( {pairs.map((p, i) => (
<FormRow <FormRow

View File

@@ -40,6 +40,9 @@ export function RequestPane({ fullHeight, request, className }: Props) {
defaultValue="body" defaultValue="body"
label="Request body" label="Request body"
> >
<TabContent value="headers" className="pl-2">
<HeaderEditor key={request.id} request={request} />
</TabContent>
<TabContent value="body"> <TabContent value="body">
<Editor <Editor
key={request.id} key={request.id}
@@ -51,9 +54,6 @@ export function RequestPane({ fullHeight, request, className }: Props) {
onChange={(body) => updateRequest.mutate({ body })} onChange={(body) => updateRequest.mutate({ body })}
/> />
</TabContent> </TabContent>
<TabContent value="headers" className="pl-2">
<HeaderEditor key={request.id} request={request} />
</TabContent>
</Tabs> </Tabs>
</div> </div>
); );

View File

@@ -1,5 +1,5 @@
import classnames from 'classnames'; import classnames from 'classnames';
import { useEffect, useMemo, useState } from 'react'; import { memo, useEffect, useMemo, useState } from 'react';
import { useDeleteAllResponses, useDeleteResponse, useResponses } from '../hooks/useResponses'; import { useDeleteAllResponses, useDeleteResponse, useResponses } from '../hooks/useResponses';
import { tryFormatJson } from '../lib/formatters'; import { tryFormatJson } from '../lib/formatters';
import { Dropdown } from './Dropdown'; import { Dropdown } from './Dropdown';
@@ -15,7 +15,7 @@ interface Props {
className?: string; className?: string;
} }
export function ResponsePane({ requestId, className }: Props) { export const ResponsePane = memo(function ResponsePane({ requestId, className }: Props) {
const [activeResponseId, setActiveResponseId] = useState<string | null>(null); const [activeResponseId, setActiveResponseId] = useState<string | null>(null);
const [viewMode, setViewMode] = useState<'pretty' | 'raw'>('pretty'); const [viewMode, setViewMode] = useState<'pretty' | 'raw'>('pretty');
const responses = useResponses(requestId); const responses = useResponses(requestId);
@@ -129,4 +129,4 @@ export function ResponsePane({ requestId, className }: Props) {
</div> </div>
</div> </div>
); );
} });

View File

@@ -22,7 +22,7 @@ export function Sidebar({ className, activeRequestId, workspaceId, requests }: P
<div <div
className={classnames( className={classnames(
className, className,
'min-w-[12rem] bg-gray-100 h-full border-r border-gray-200 relative', 'min-w-[12rem] bg-gray-100 h-full border-r border-gray-200 relative grid grid-rows-[auto,1fr]',
)} )}
> >
<HStack as={WindowDragRegion} alignItems="center" justifyContent="end"> <HStack as={WindowDragRegion} alignItems="center" justifyContent="end">
@@ -34,7 +34,7 @@ export function Sidebar({ className, activeRequestId, workspaceId, requests }: P
}} }}
/> />
</HStack> </HStack>
<VStack as="ul" className="py-3 px-2" space={1}> <VStack as="ul" className="py-3 px-2 overflow-auto h-full" space={1}>
{requests.map((r) => ( {requests.map((r) => (
<SidebarItem key={r.id} request={r} active={r.id === activeRequestId} /> <SidebarItem key={r.id} request={r} active={r.id === activeRequestId} />
))} ))}

View File

@@ -23,25 +23,21 @@ export function Tabs({ defaultValue, label, children, tabs, className, tabListCl
<T.Root <T.Root
defaultValue={defaultValue} defaultValue={defaultValue}
onValueChange={setValue} onValueChange={setValue}
className={classnames( className={classnames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1')}
className,
// 'h-full overflow-hidden grid grid-rows-[auto_minmax(0,1fr)]',
'h-full flex flex-col min-h-[min-content]',
)}
> >
<T.List <T.List
aria-label={label} aria-label={label}
className={classnames(tabListClassName, 'h-auto flex items-center')} className={classnames(tabListClassName, 'h-auto flex items-center overflow-x-auto mb-1 pb-1')}
> >
<ScrollArea className="w-full pb-2"> {/*<ScrollArea className="w-full pb-2">*/}
<HStack space={1}> <HStack space={1}>
{tabs.map((t) => ( {tabs.map((t) => (
<TabTrigger key={t.value} value={t.value} active={t.value === value}> <TabTrigger key={t.value} value={t.value} active={t.value === value}>
{t.label} {t.label}
</TabTrigger> </TabTrigger>
))} ))}
</HStack> </HStack>
</ScrollArea> {/*</ScrollArea>*/}
</T.List> </T.List>
{children} {children}
</T.Root> </T.Root>
@@ -81,7 +77,7 @@ export function TabContent({ value, children, className }: TabContentProps) {
<T.Content <T.Content
forceMount forceMount
value={value} value={value}
className={classnames(className, 'tab-content', 'w-full overflow-auto flex-grow h-0')} className={classnames(className, 'tab-content', 'w-full h-full overflow-auto')}
> >
{children} {children}
</T.Content> </T.Content>

View File

@@ -27,6 +27,7 @@ export function useRequestUpdate(request: HttpRequest | null) {
} }
const updatedRequest = { ...request, ...patch }; const updatedRequest = { ...request, ...patch };
console.log('UPDATE REQUEST', updatedRequest.url);
await invoke('update_request', { await invoke('update_request', {
request: { request: {

View File

@@ -23,6 +23,16 @@
cursor: default; cursor: default;
} }
/* Style the scrollbars */
::-webkit-scrollbar-corner,
::-webkit-scrollbar {
@apply w-1.5 h-1.5 bg-gray-300/10;
}
::-webkit-scrollbar-thumb {
@apply bg-gray-200 hover:bg-gray-300 rounded-full;
}
:root { :root {
color-scheme: light dark; color-scheme: light dark;
--transition-duration: 100ms ease-in-out; --transition-duration: 100ms ease-in-out;

View File

@@ -1,6 +1,7 @@
import classnames from 'classnames'; import classnames from 'classnames';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { useWindowSize } from 'react-use'; import { useWindowSize } from 'react-use';
import { HeaderEditor } from '../components/HeaderEditor';
import { RequestPane } from '../components/RequestPane'; import { RequestPane } from '../components/RequestPane';
import { ResponsePane } from '../components/ResponsePane'; import { ResponsePane } from '../components/ResponsePane';
import { Sidebar } from '../components/Sidebar'; import { Sidebar } from '../components/Sidebar';
@@ -22,7 +23,7 @@ export default function Workspace() {
const isH = width > 900; const isH = width > 900;
return ( return (
<div className="grid grid-cols-[auto_1fr] h-full text-gray-900"> <div className="grid grid-cols-[auto_1fr] grid-rows-1 h-full text-gray-900">
<Sidebar <Sidebar
requests={requests ?? []} requests={requests ?? []}
workspaceId={workspaceId} workspaceId={workspaceId}
@@ -39,8 +40,10 @@ export default function Workspace() {
</HStack> </HStack>
<div <div
className={classnames( className={classnames(
'grid overflow-auto', 'grid',
isH ? 'grid-cols-[1fr_1fr]' : 'grid-rows-[minmax(0,auto)_minmax(0,100%)]', isH
? 'grid-cols-[1fr_1fr] grid-rows-1'
: 'grid-cols-1 grid-rows-[minmax(0,auto)_minmax(0,100%)]',
)} )}
> >
<RequestPane <RequestPane

View File

@@ -4,7 +4,7 @@ import topLevelAwait from 'vite-plugin-top-level-await';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
const config = defineConfig({ const config = defineConfig({
plugins: [react(), topLevelAwait()], plugins: [react({}), topLevelAwait()],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// prevent vite from obscuring rust errors // prevent vite from obscuring rust errors