Short method tags and hide active in cmd+k

This commit is contained in:
Gregory Schier
2024-06-07 22:39:11 -07:00
parent f9412e6d8f
commit b456e8ce94
3 changed files with 61 additions and 12 deletions

View File

@@ -2,6 +2,8 @@ import classNames from 'classnames';
import type { KeyboardEvent, ReactNode } from 'react'; import type { KeyboardEvent, ReactNode } from 'react';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId'; import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId';
import { useActiveRequestId } from '../hooks/useActiveRequestId';
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
import { useAppRoutes } from '../hooks/useAppRoutes'; import { useAppRoutes } from '../hooks/useAppRoutes';
import { useOpenWorkspace } from '../hooks/useOpenWorkspace'; import { useOpenWorkspace } from '../hooks/useOpenWorkspace';
import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentRequests } from '../hooks/useRecentRequests';
@@ -10,25 +12,28 @@ import { useRequests } from '../hooks/useRequests';
import { useWorkspaces } from '../hooks/useWorkspaces'; import { useWorkspaces } from '../hooks/useWorkspaces';
import { fallbackRequestName } from '../lib/fallbackRequestName'; import { fallbackRequestName } from '../lib/fallbackRequestName';
import { Heading } from './core/Heading'; import { Heading } from './core/Heading';
import { HttpMethodTag } from './core/HttpMethodTag';
import { Icon } from './core/Icon'; import { Icon } from './core/Icon';
import { PlainInput } from './core/PlainInput'; import { PlainInput } from './core/PlainInput';
import { HStack } from './core/Stacks';
interface CommandPaletteGroup { interface CommandPaletteGroup {
key: string; key: string;
label: string; label: ReactNode;
items: CommandPaletteItem[]; items: CommandPaletteItem[];
} }
interface CommandPaletteItem { type CommandPaletteItem = {
key: string; key: string;
label: string;
onSelect: () => void; onSelect: () => void;
} } & ({ searchText: string; label: ReactNode } | { label: string });
export function CommandPalette({ onClose }: { onClose: () => void }) { export function CommandPalette({ onClose }: { onClose: () => void }) {
const [selectedItemKey, setSelectedItemKey] = useState<string | null>(null); const [selectedItemKey, setSelectedItemKey] = useState<string | null>(null);
const routes = useAppRoutes(); const routes = useAppRoutes();
const activeEnvironmentId = useActiveEnvironmentId(); const activeEnvironmentId = useActiveEnvironmentId();
const activeRequestId = useActiveRequestId();
const activeWorkspaceId = useActiveWorkspaceId();
const workspaces = useWorkspaces(); const workspaces = useWorkspaces();
const recentWorkspaces = useRecentWorkspaces(); const recentWorkspaces = useRecentWorkspaces();
const requests = useRequests(); const requests = useRequests();
@@ -78,9 +83,19 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
}; };
for (const r of sortedRequests.slice(0, 4)) { for (const r of sortedRequests.slice(0, 4)) {
if (r.id === activeRequestId) {
continue;
}
requestGroup.items.push({ requestGroup.items.push({
key: `switch-request-${r.id}`, key: `switch-request-${r.id}`,
label: fallbackRequestName(r), searchText: `${r.method} ${r.name}`,
label: (
<HStack space={2}>
<HttpMethodTag className="text-fg-subtler" shortNames request={r} />
<div className="truncate">{fallbackRequestName(r)}</div>
</HStack>
),
onSelect: () => { onSelect: () => {
return routes.navigate('request', { return routes.navigate('request', {
workspaceId: r.workspaceId, workspaceId: r.workspaceId,
@@ -98,6 +113,9 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
}; };
for (const w of sortedWorkspaces.slice(0, 4)) { for (const w of sortedWorkspaces.slice(0, 4)) {
if (w.id === activeWorkspaceId) {
continue;
}
workspaceGroup.items.push({ workspaceGroup.items.push({
key: `switch-workspace-${w.id}`, key: `switch-workspace-${w.id}`,
label: w.name, label: w.name,
@@ -106,13 +124,24 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
} }
return [requestGroup, workspaceGroup]; return [requestGroup, workspaceGroup];
}, [activeEnvironmentId, openWorkspace, routes, sortedRequests, sortedWorkspaces]); }, [
activeEnvironmentId,
activeRequestId,
activeWorkspaceId,
openWorkspace,
routes,
sortedRequests,
sortedWorkspaces,
]);
const filteredGroups = useMemo( const filteredGroups = useMemo(
() => () =>
groups groups
.map((g) => { .map((g) => {
g.items = g.items.filter((v) => v.label.toLowerCase().includes(command.toLowerCase())); g.items = g.items.filter((v) => {
const s = 'searchText' in v ? v.searchText : v.label;
return s.toLowerCase().includes(command.toLowerCase());
});
return g; return g;
}) })
.filter((g) => g.items.length > 0), .filter((g) => g.items.length > 0),

View File

@@ -53,7 +53,7 @@ export function RecentRequestsDropdown({ className }: Pick<ButtonProps, 'classNa
key: request.id, key: request.id,
label: fallbackRequestName(request), label: fallbackRequestName(request),
// leftSlot: <CountBadge className="!ml-0 px-0 w-5" count={recentRequestItems.length} />, // leftSlot: <CountBadge className="!ml-0 px-0 w-5" count={recentRequestItems.length} />,
leftSlot: <HttpMethodTag request={request} />, leftSlot: <HttpMethodTag className="text-right" shortNames request={request} />,
onSelect: () => { onSelect: () => {
routes.navigate('request', { routes.navigate('request', {
requestId: request.id, requestId: request.id,

View File

@@ -4,9 +4,10 @@ import type { GrpcRequest, HttpRequest } from '../../lib/models';
interface Props { interface Props {
request: HttpRequest | GrpcRequest; request: HttpRequest | GrpcRequest;
className?: string; className?: string;
shortNames?: boolean;
} }
const methodMap: Record<string, string> = { const longMethodMap = {
get: 'GET', get: 'GET',
put: 'PUT', put: 'PUT',
post: 'POST', post: 'POST',
@@ -15,9 +16,20 @@ const methodMap: Record<string, string> = {
options: 'OPTIONS', options: 'OPTIONS',
head: 'HEAD', head: 'HEAD',
grpc: 'GRPC', grpc: 'GRPC',
} as const;
const shortMethodMap: Record<keyof typeof longMethodMap, string> = {
get: 'GET',
put: 'PUT',
post: 'POST',
patch: 'PTCH',
delete: 'DEL',
options: 'OPTS',
head: 'HEAD',
grpc: 'GRPC',
}; };
export function HttpMethodTag({ request, className }: Props) { export function HttpMethodTag({ shortNames, request, className }: Props) {
const method = const method =
request.model === 'http_request' && request.bodyType === 'graphql' request.model === 'http_request' && request.bodyType === 'graphql'
? 'GQL' ? 'GQL'
@@ -26,9 +38,17 @@ export function HttpMethodTag({ request, className }: Props) {
: request.method; : request.method;
const m = method.toLowerCase(); const m = method.toLowerCase();
const methodMap: Record<string, string> = shortNames ? shortMethodMap : longMethodMap;
return ( return (
<span className={classNames(className, 'text-xs font-mono text-fg-subtle')}> <span
{methodMap[m] ?? m.slice(0, 3).toUpperCase()} className={classNames(
className,
'text-xs font-mono text-fg-subtle',
'pt-[0.25em]', // Fix for monospace font not vertically centering
shortNames && 'w-[2.5em]',
)}
>
{methodMap[m] ?? m.slice(0, 4).toUpperCase()}
</span> </span>
); );
} }