mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-01-11 20:00:29 +01:00
Sidebar methods and fix model hooks
This commit is contained in:
@@ -1564,7 +1564,7 @@ fn main() {
|
||||
"App Config Dir: {}",
|
||||
app_config_dir.as_path().to_string_lossy(),
|
||||
);
|
||||
info!("App Data Dir: {}", app_data_dir.as_path().to_string_lossy(),);
|
||||
info!("App Data Dir: {}", app_data_dir.as_path().to_string_lossy());
|
||||
let dir = match is_dev() {
|
||||
true => current_dir().unwrap(),
|
||||
false => app_data_dir,
|
||||
|
||||
@@ -46,8 +46,6 @@ export function GlobalHooks() {
|
||||
}, [location.pathname]);
|
||||
|
||||
useListenToTauriEvent<Model>('upserted_model', ({ payload, windowLabel }) => {
|
||||
if (shouldIgnoreEvent(payload, windowLabel)) return;
|
||||
|
||||
const queryKey =
|
||||
payload.model === 'http_request'
|
||||
? httpRequestsQueryKey(payload)
|
||||
@@ -74,7 +72,7 @@ export function GlobalHooks() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.model === 'http_request') {
|
||||
if (payload.model === 'http_request' && windowLabel !== appWindow.label) {
|
||||
wasUpdatedExternally(payload.id);
|
||||
}
|
||||
|
||||
@@ -82,21 +80,19 @@ export function GlobalHooks() {
|
||||
payload.model,
|
||||
);
|
||||
|
||||
if (!shouldIgnoreModel(payload)) {
|
||||
queryClient.setQueryData<Model[]>(queryKey, (values = []) => {
|
||||
const index = values.findIndex((v) => modelsEq(v, payload)) ?? -1;
|
||||
if (index >= 0) {
|
||||
return [...values.slice(0, index), payload, ...values.slice(index + 1)];
|
||||
} else {
|
||||
return pushToFront ? [payload, ...(values ?? [])] : [...(values ?? []), payload];
|
||||
}
|
||||
});
|
||||
}
|
||||
if (shouldIgnoreModel(payload)) return;
|
||||
|
||||
queryClient.setQueryData<Model[]>(queryKey, (values = []) => {
|
||||
const index = values.findIndex((v) => modelsEq(v, payload)) ?? -1;
|
||||
if (index >= 0) {
|
||||
return [...values.slice(0, index), payload, ...values.slice(index + 1)];
|
||||
} else {
|
||||
return pushToFront ? [payload, ...(values ?? [])] : [...(values ?? []), payload];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useListenToTauriEvent<Model>('deleted_model', ({ payload, windowLabel }) => {
|
||||
if (shouldIgnoreEvent(payload, windowLabel)) return;
|
||||
|
||||
if (shouldIgnoreModel(payload)) return;
|
||||
|
||||
if (payload.model === 'workspace') {
|
||||
@@ -142,9 +138,6 @@ function removeById<T extends { id: string }>(model: T) {
|
||||
return (entries: T[] | undefined) => entries?.filter((e) => e.id !== model.id);
|
||||
}
|
||||
|
||||
const shouldIgnoreEvent = (payload: Model, windowLabel: string) =>
|
||||
windowLabel === appWindow.label && payload.model !== 'http_response';
|
||||
|
||||
const shouldIgnoreModel = (payload: Model) => {
|
||||
if (payload.model === 'key_value') {
|
||||
return payload.namespace === NAMESPACE_NO_SYNC;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId';
|
||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
|
||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useGrpcRequests } from '../hooks/useGrpcRequests';
|
||||
import { useHotKey } from '../hooks/useHotKey';
|
||||
import { useRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useHttpRequests } from '../hooks/useHttpRequests';
|
||||
@@ -19,10 +20,12 @@ export function RecentRequestsDropdown({ className }: Pick<ButtonProps, 'classNa
|
||||
const activeRequest = useActiveRequest();
|
||||
const activeWorkspaceId = useActiveWorkspaceId();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
const requests = useHttpRequests();
|
||||
const httpRequests = useHttpRequests();
|
||||
const grpcRequests = useGrpcRequests();
|
||||
const routes = useAppRoutes();
|
||||
const allRecentRequestIds = useRecentRequests();
|
||||
const recentRequestIds = useMemo(() => allRecentRequestIds.slice(1), [allRecentRequestIds]);
|
||||
const requests = useMemo(() => [...httpRequests, ...grpcRequests], [httpRequests, grpcRequests]);
|
||||
|
||||
// Toggle the menu on Cmd+k
|
||||
useKey('k', (e) => {
|
||||
|
||||
@@ -39,6 +39,7 @@ import type { Folder, GrpcRequest, HttpRequest, Workspace } from '../lib/models'
|
||||
import { isResponseLoading } from '../lib/models';
|
||||
import type { DropdownItem } from './core/Dropdown';
|
||||
import { ContextMenu } from './core/Dropdown';
|
||||
import { HttpMethodTag } from './core/HttpMethodTag';
|
||||
import { Icon } from './core/Icon';
|
||||
import { InlineCode } from './core/InlineCode';
|
||||
import { VStack } from './core/Stacks';
|
||||
@@ -488,6 +489,13 @@ function SidebarItems({
|
||||
: 'New Folder'
|
||||
}
|
||||
itemModel={child.item.model}
|
||||
itemPrefix={
|
||||
child.item.model === 'http_request' ? (
|
||||
<HttpMethodTag className="opacity-50">{child.item.method}</HttpMethodTag>
|
||||
) : child.item.model === 'grpc_request' ? (
|
||||
<HttpMethodTag className="opacity-50">gRPC</HttpMethodTag>
|
||||
) : null
|
||||
}
|
||||
onMove={handleMove}
|
||||
onEnd={handleEnd}
|
||||
onSelect={onSelect}
|
||||
@@ -531,6 +539,7 @@ type SidebarItemProps = {
|
||||
itemName: string;
|
||||
itemFallbackName: string;
|
||||
itemModel: string;
|
||||
itemPrefix: ReactNode;
|
||||
useProminentStyles?: boolean;
|
||||
selected?: boolean;
|
||||
draggable?: boolean;
|
||||
@@ -546,6 +555,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
itemFallbackName,
|
||||
itemId,
|
||||
itemModel,
|
||||
itemPrefix,
|
||||
useProminentStyles,
|
||||
selected,
|
||||
onSelect,
|
||||
@@ -733,7 +743,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
data-active={isActive}
|
||||
data-selected={selected}
|
||||
className={classNames(
|
||||
'w-full flex items-center text-sm h-xs px-2 rounded-md transition-colors',
|
||||
'w-full flex gap-2 items-center text-sm h-xs pl-2 rounded-md transition-colors',
|
||||
editing && 'ring-1 focus-within:ring-focus',
|
||||
isActive && 'bg-highlightSecondary text-gray-800',
|
||||
!isActive &&
|
||||
@@ -746,37 +756,40 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
size="sm"
|
||||
icon="chevronRight"
|
||||
className={classNames(
|
||||
'-ml-0.5 mr-2 transition-transform',
|
||||
'-ml-0.5 transition-transform opacity-50',
|
||||
!isCollapsed(itemId) && 'transform rotate-90',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{editing ? (
|
||||
<input
|
||||
ref={handleFocus}
|
||||
defaultValue={itemName}
|
||||
className="bg-transparent outline-none w-full"
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={handleInputKeyDown}
|
||||
/>
|
||||
) : (
|
||||
<span className="truncate">{itemName || itemFallbackName}</span>
|
||||
)}
|
||||
{latestGrpcConnection ? (
|
||||
<div className="ml-auto">
|
||||
{latestGrpcConnection.elapsed === 0 && (
|
||||
<Icon spin size="sm" icon="update" className="text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
) : latestHttpResponse ? (
|
||||
<div className="ml-auto">
|
||||
{isResponseLoading(latestHttpResponse) ? (
|
||||
<Icon spin size="sm" icon="update" className="text-gray-400" />
|
||||
) : (
|
||||
<StatusTag className="text-2xs dark:opacity-80" response={latestHttpResponse} />
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex items-end gap-2 min-w-0">
|
||||
{itemPrefix}
|
||||
{editing ? (
|
||||
<input
|
||||
ref={handleFocus}
|
||||
defaultValue={itemName}
|
||||
className="bg-transparent outline-none w-full"
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={handleInputKeyDown}
|
||||
/>
|
||||
) : (
|
||||
<span className="truncate">{itemName || itemFallbackName}</span>
|
||||
)}
|
||||
{latestGrpcConnection ? (
|
||||
<div className="ml-auto">
|
||||
{latestGrpcConnection.elapsed === 0 && (
|
||||
<Icon spin size="sm" icon="update" className="text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
) : latestHttpResponse ? (
|
||||
<div className="ml-auto">
|
||||
{isResponseLoading(latestHttpResponse) ? (
|
||||
<Icon spin size="sm" icon="update" className="text-gray-400" />
|
||||
) : (
|
||||
<StatusTag className="text-2xs dark:opacity-80" response={latestHttpResponse} />
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
{children}
|
||||
|
||||
26
src-web/components/core/HttpMethodTag.tsx
Normal file
26
src-web/components/core/HttpMethodTag.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface Props {
|
||||
children: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const methodMap: Record<string, string> = {
|
||||
get: 'GET',
|
||||
put: 'PUT',
|
||||
post: 'POST',
|
||||
patch: 'PATCH',
|
||||
delete: 'DELETE',
|
||||
options: 'OPTIONS',
|
||||
head: 'HEAD',
|
||||
grpc: 'gRPC',
|
||||
};
|
||||
|
||||
export function HttpMethodTag({ children: method, className }: Props) {
|
||||
const m = method.toLowerCase();
|
||||
return (
|
||||
<span className={classNames(className, 'text-2xs font-mono')}>
|
||||
{methodMap[m] ?? m.slice(0, 3).toUpperCase()}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -57,7 +57,6 @@ export function useGrpc(req: GrpcRequest | null, conn: GrpcConnection | null) {
|
||||
queryKey: ['grpc_reflect', req?.id ?? 'n/a', debouncedUrl],
|
||||
refetchOnWindowFocus: false,
|
||||
queryFn: async () => {
|
||||
console.log('useGrpc.reflect', { requestId });
|
||||
return (await minPromiseMillis(
|
||||
invoke('cmd_grpc_reflect', { requestId }),
|
||||
300,
|
||||
|
||||
@@ -71,11 +71,11 @@ module.exports = {
|
||||
red: color('red'),
|
||||
orange: color('orange'),
|
||||
yellow: color('yellow'),
|
||||
gray: color('gray'),
|
||||
blue: color('blue'),
|
||||
green: color('green'),
|
||||
pink: color('pink'),
|
||||
violet: color('violet'),
|
||||
gray: color('gray'),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
||||
Reference in New Issue
Block a user