mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-20 00:23:58 +01:00
Download response, and some fixes
This commit is contained in:
@@ -58,7 +58,7 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo
|
||||
? {
|
||||
key: 'edit',
|
||||
label: 'Manage Environments',
|
||||
hotkeyAction: 'environmentEditor.toggle',
|
||||
hotKeyAction: 'environmentEditor.toggle',
|
||||
leftSlot: <Icon icon="box" />,
|
||||
onSelect: showEnvironmentDialog,
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export function SettingsDropdown() {
|
||||
{
|
||||
key: 'hotkeys',
|
||||
label: 'Keyboard shortcuts',
|
||||
hotkeyAction: 'hotkeys.showHelp',
|
||||
hotKeyAction: 'hotkeys.showHelp',
|
||||
leftSlot: <Icon icon="keyboard" />,
|
||||
onSelect: () => {
|
||||
dialog.show({
|
||||
@@ -77,7 +77,7 @@ export function SettingsDropdown() {
|
||||
{
|
||||
key: 'settings',
|
||||
label: 'Settings',
|
||||
hotkeyAction: 'settings.show',
|
||||
hotKeyAction: 'settings.show',
|
||||
leftSlot: <Icon icon="settings" />,
|
||||
onSelect: () => {
|
||||
dialog.show({
|
||||
|
||||
@@ -23,6 +23,7 @@ import { useLatestResponse } from '../hooks/useLatestResponse';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useRequests } from '../hooks/useRequests';
|
||||
import { useSendManyRequests } from '../hooks/useSendFolder';
|
||||
import { useSendRequest } from '../hooks/useSendRequest';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { useUpdateAnyFolder } from '../hooks/useUpdateAnyFolder';
|
||||
import { useUpdateAnyRequest } from '../hooks/useUpdateAnyRequest';
|
||||
@@ -61,6 +62,7 @@ export function Sidebar({ className }: Props) {
|
||||
const folders = useFolders();
|
||||
const deleteAnyRequest = useDeleteAnyRequest();
|
||||
const activeWorkspace = useActiveWorkspace();
|
||||
const duplicateRequest = useDuplicateRequest({ id: activeRequestId, navigateAfter: true });
|
||||
const routes = useAppRoutes();
|
||||
const [hasFocus, setHasFocus] = useState<boolean>(false);
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
@@ -76,6 +78,10 @@ export function Sidebar({ className }: Props) {
|
||||
namespace: NAMESPACE_NO_SYNC,
|
||||
});
|
||||
|
||||
useHotKey('request.duplicate', () => {
|
||||
duplicateRequest.mutate();
|
||||
});
|
||||
|
||||
const isCollapsed = useCallback(
|
||||
(id: string) => collapsed.value?.[id] ?? false,
|
||||
[collapsed.value],
|
||||
@@ -517,18 +523,20 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
}: SidebarItemProps,
|
||||
ref: ForwardedRef<HTMLLIElement>,
|
||||
) {
|
||||
const activeRequest = useActiveRequest();
|
||||
const createRequest = useCreateRequest();
|
||||
const createFolder = useCreateFolder();
|
||||
const deleteFolder = useDeleteFolder(itemId);
|
||||
const deleteRequest = useDeleteRequest(itemId);
|
||||
const duplicateRequest = useDuplicateRequest({ id: itemId, navigateAfter: true });
|
||||
const sendRequest = useSendRequest(itemId);
|
||||
const sendAndDownloadRequest = useSendRequest(itemId, { download: true });
|
||||
const sendManyRequests = useSendManyRequests();
|
||||
const latestResponse = useLatestResponse(itemId);
|
||||
const updateRequest = useUpdateRequest(itemId);
|
||||
const updateAnyFolder = useUpdateAnyFolder();
|
||||
const prompt = usePrompt();
|
||||
const [editing, setEditing] = useState<boolean>(false);
|
||||
const activeRequest = useActiveRequest();
|
||||
const isActive = activeRequest?.id === itemId;
|
||||
|
||||
const handleSubmitNameEdit = useCallback(
|
||||
@@ -599,7 +607,6 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
leftSlot: <Icon icon="sendHorizontal" />,
|
||||
onSelect: () => sendManyRequests.mutate(child.children.map((c) => c.item.id)),
|
||||
},
|
||||
{ type: 'separator', label: itemName },
|
||||
{
|
||||
key: 'rename',
|
||||
label: 'Rename',
|
||||
@@ -641,15 +648,29 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
key: 'sendRequest',
|
||||
label: 'Send',
|
||||
hotKeyAction: 'request.send',
|
||||
hotKeyLabelOnly: true, // Already bound in URL bar
|
||||
leftSlot: <Icon icon="sendHorizontal" />,
|
||||
onSelect: () => sendRequest.mutate(),
|
||||
},
|
||||
{
|
||||
key: 'sendAndDownloadRequest',
|
||||
label: 'Send and Download',
|
||||
leftSlot: <Icon icon="download" />,
|
||||
onSelect: () => sendAndDownloadRequest.mutate(),
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
key: 'duplicateRequest',
|
||||
label: 'Duplicate',
|
||||
hotkeyAction: 'request.duplicate',
|
||||
hotKeyAction: 'request.duplicate',
|
||||
hotKeyLabelOnly: true, // Would trigger for every request (bad)
|
||||
leftSlot: <Icon icon="copy" />,
|
||||
onSelect: () => {
|
||||
if (activeRequest?.id === itemId) {
|
||||
duplicateRequest.mutate();
|
||||
}
|
||||
duplicateRequest.mutate();
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SidebarActions = memo(function SidebarActions() {
|
||||
{
|
||||
key: 'create-request',
|
||||
label: 'New Request',
|
||||
hotkeyAction: 'request.create',
|
||||
hotKeyAction: 'request.create',
|
||||
onSelect: () => createRequest.mutate({}),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ export type DropdownItemDefault = {
|
||||
key: string;
|
||||
type?: 'default';
|
||||
label: ReactNode;
|
||||
hotkeyAction?: HotkeyAction;
|
||||
hotKeyAction?: HotkeyAction;
|
||||
hotKeyLabelOnly?: boolean;
|
||||
variant?: 'danger';
|
||||
disabled?: boolean;
|
||||
hidden?: boolean;
|
||||
@@ -338,12 +339,13 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
|
||||
<>
|
||||
{items.map(
|
||||
(item) =>
|
||||
item.type !== 'separator' && (
|
||||
item.type !== 'separator' &&
|
||||
!item.hotKeyLabelOnly && (
|
||||
<MenuItemHotKey
|
||||
key={item.key}
|
||||
onSelect={handleSelect}
|
||||
item={item}
|
||||
action={item.hotkeyAction}
|
||||
action={item.hotKeyAction}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
@@ -440,7 +442,7 @@ function MenuItem({ className, focused, onFocus, item, onSelect, ...props }: Men
|
||||
[focused],
|
||||
);
|
||||
|
||||
const rightSlot = item.rightSlot ?? <HotKey action={item.hotkeyAction ?? null} />;
|
||||
const rightSlot = item.rightSlot ?? <HotKey action={item.hotKeyAction ?? null} />;
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -121,6 +121,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
|
||||
ref={wrapperRef}
|
||||
className={classNames(
|
||||
'w-full',
|
||||
'pointer-events-auto', // Just in case we're placing in disabled parent
|
||||
labelPosition === 'left' && 'flex items-center gap-2',
|
||||
labelPosition === 'top' && 'flex-row gap-0.5',
|
||||
)}
|
||||
|
||||
@@ -1,15 +1,40 @@
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { save } from '@tauri-apps/api/dialog';
|
||||
import slugify from 'slugify';
|
||||
import { trackEvent } from '../lib/analytics';
|
||||
import type { HttpResponse } from '../lib/models';
|
||||
import { getRequest } from '../lib/store';
|
||||
import { useActiveEnvironmentId } from './useActiveEnvironmentId';
|
||||
import { useAlert } from './useAlert';
|
||||
|
||||
export function useSendAnyRequest() {
|
||||
export function useSendAnyRequest(options: { download?: boolean } = {}) {
|
||||
const environmentId = useActiveEnvironmentId();
|
||||
const alert = useAlert();
|
||||
return useMutation<HttpResponse, string, string | null>({
|
||||
mutationFn: (id) => invoke('send_request', { requestId: id, environmentId }),
|
||||
return useMutation<HttpResponse | null, string, string | null>({
|
||||
mutationFn: async (id) => {
|
||||
const request = await getRequest(id);
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let downloadDir: string | null = null;
|
||||
if (options.download) {
|
||||
downloadDir = await save({
|
||||
title: 'Select Download Destination',
|
||||
defaultPath: slugify(request.name, { lower: true, trim: true, strict: true }),
|
||||
});
|
||||
if (downloadDir == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return invoke('send_request', {
|
||||
requestId: id,
|
||||
environmentId,
|
||||
downloadDir: downloadDir,
|
||||
});
|
||||
},
|
||||
onSettled: () => trackEvent('HttpRequest', 'Send'),
|
||||
onError: (err) => alert({ title: 'Export Failed', body: err }),
|
||||
});
|
||||
|
||||
@@ -2,9 +2,9 @@ import { useMutation } from '@tanstack/react-query';
|
||||
import type { HttpResponse } from '../lib/models';
|
||||
import { useSendAnyRequest } from './useSendAnyRequest';
|
||||
|
||||
export function useSendRequest(id: string | null) {
|
||||
const sendAnyRequest = useSendAnyRequest();
|
||||
return useMutation<HttpResponse, string>({
|
||||
export function useSendRequest(id: string | null, options: { download?: boolean } = {}) {
|
||||
const sendAnyRequest = useSendAnyRequest(options);
|
||||
return useMutation<HttpResponse | null, string>({
|
||||
mutationFn: () => sendAnyRequest.mutateAsync(id),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user