diff --git a/.eslintrc.cjs b/.eslintrc.cjs index cb089e6f..eb33d92c 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -8,6 +8,7 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'eslint-config-prettier', ], + plugins: ['react-refresh'], parser: '@typescript-eslint/parser', parserOptions: { project: ['./tsconfig.json'], @@ -32,6 +33,7 @@ module.exports = { }, }, rules: { + 'react-refresh/only-export-components': 'error', 'jsx-a11y/no-autofocus': 'off', 'react/react-in-jsx-scope': 'off', 'import/no-unresolved': 'off', diff --git a/package-lock.json b/package-lock.json index d190801c..e7e658cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1826,15 +1826,6 @@ "react": ">=16.8" } }, - "node_modules/@remix-run/router": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz", - "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rollup/plugin-virtual": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", @@ -6580,6 +6571,16 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.16.tgz", + "integrity": "sha512-slterMlxAhov/DZO8NScf6mEeMBBXodFUolijDvrtTxyezyLoTQaa73FyYus/VbTdftd8wBgBxPMRk3poleXNQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -12323,38 +12324,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-router": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz", - "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.19.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz", - "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.19.2", - "react-router": "6.26.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -16001,7 +15970,6 @@ "react-helmet-async": "^2.0.5", "react-markdown": "^9.0.1", "react-pdf": "^9.1.0", - "react-router-dom": "^6.26.2", "react-use": "^17.5.1", "remark-gfm": "^4.0.0", "slugify": "^1.6.6", @@ -16026,6 +15994,7 @@ "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.20", "decompress": "^4.2.1", + "eslint-plugin-react-refresh": "^0.4.16", "internal-ip": "^8.0.0", "postcss": "^8.4.45", "postcss-nesting": "^13.0.0", diff --git a/src-web/components/CommandPalette.tsx b/src-web/components/CommandPalette.tsx index 336524cf..2b10ea7c 100644 --- a/src-web/components/CommandPalette.tsx +++ b/src-web/components/CommandPalette.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from '@tanstack/react-router'; import classNames from 'classnames'; import { fuzzyFilter } from 'fuzzbunny'; import type { KeyboardEvent, ReactNode } from 'react'; @@ -11,6 +12,7 @@ import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest'; import { useCreateWorkspace } from '../hooks/useCreateWorkspace'; import { useDebouncedState } from '../hooks/useDebouncedState'; import { useDeleteRequest } from '../hooks/useDeleteRequest'; +import { useDialog } from '../hooks/useDialog'; import { useEnvironments } from '../hooks/useEnvironments'; import type { HotkeyAction } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey'; @@ -27,8 +29,6 @@ import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; import { useSidebarHidden } from '../hooks/useSidebarHidden'; import { useWorkspaces } from '../hooks/useWorkspaces'; import { fallbackRequestName } from '../lib/fallbackRequestName'; -import { router } from '../main'; -import { Route } from '../routes/workspaces/$workspaceId/requests/$requestId'; import { CookieDialog } from './CookieDialog'; import { Button } from './core/Button'; import { Heading } from './core/Heading'; @@ -37,7 +37,6 @@ import { HttpMethodTag } from './core/HttpMethodTag'; import { Icon } from './core/Icon'; import { PlainInput } from './core/PlainInput'; import { HStack } from './core/Stacks'; -import { useDialog } from './DialogContext'; import { EnvironmentEditDialog } from './EnvironmentEditDialog'; interface CommandPaletteGroup { @@ -78,6 +77,7 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { const deleteRequest = useDeleteRequest(activeRequest?.id ?? null); const [, setSidebarHidden] = useSidebarHidden(); const openSettings = useOpenSettings(); + const navigate = useNavigate(); const workspaceCommands = useMemo(() => { const commands: CommandPaletteItem[] = [ @@ -267,9 +267,9 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
{fallbackRequestName(r)}
), - onSelect: () => { - router.navigate({ - to: Route.fullPath, + onSelect: async () => { + await navigate({ + to: '/workspaces/$workspaceId/requests/$requestId', params: { workspaceId: r.workspaceId, requestId: r.id, @@ -315,8 +315,9 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { }, [ workspaceCommands, sortedRequests, - activeEnvironment?.id, + navigate, sortedEnvironments, + activeEnvironment?.id, setActiveEnvironmentId, sortedWorkspaces, openWorkspace, diff --git a/src-web/components/CookieDropdown.tsx b/src-web/components/CookieDropdown.tsx index 5843bbb3..124b5aab 100644 --- a/src-web/components/CookieDropdown.tsx +++ b/src-web/components/CookieDropdown.tsx @@ -9,7 +9,7 @@ import { Dropdown, type DropdownItem } from './core/Dropdown'; import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; import { InlineCode } from './core/InlineCode'; -import { useDialog } from './DialogContext'; +import { useDialog } from '../hooks/useDialog'; export function CookieDropdown() { const cookieJars = useCookieJars() ?? []; diff --git a/src-web/components/DialogContext.tsx b/src-web/components/DialogContext.tsx index 961521f5..68f48ae6 100644 --- a/src-web/components/DialogContext.tsx +++ b/src-web/components/DialogContext.tsx @@ -1,80 +1,5 @@ -import React, { createContext, useContext, useMemo, useState } from 'react'; -import { trackEvent } from '../lib/analytics'; -import type { DialogProps } from './core/Dialog'; -import { Dialog } from './core/Dialog'; - -type DialogEntry = { - id: string; - render: ({ hide }: { hide: () => void }) => React.ReactNode; -} & Omit; - -interface State { - dialogs: DialogEntry[]; - actions: Actions; -} - -interface Actions { - show: (d: DialogEntry) => void; - toggle: (d: DialogEntry) => void; - hide: (id: string) => void; -} +import { createContext } from 'react'; +import type { DialogState } from './Dialogs'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -const DialogContext = createContext({} as State); - -export const DialogProvider = ({ children }: { children: React.ReactNode }) => { - const [dialogs, setDialogs] = useState([]); - const actions = useMemo( - () => ({ - show({ id, ...props }: DialogEntry) { - trackEvent('dialog', 'show', { id }); - setDialogs((a) => [...a.filter((d) => d.id !== id), { id, ...props }]); - }, - toggle({ id, ...props }: DialogEntry) { - if (dialogs.some((d) => d.id === id)) this.hide(id); - else this.show({ id, ...props }); - }, - hide: (id: string) => { - setDialogs((a) => a.filter((d) => d.id !== id)); - }, - }), - [dialogs], - ); - - const state: State = { - dialogs, - actions, - }; - - return {children}; -}; - -function DialogInstance({ id, render, onClose, ...props }: DialogEntry) { - const { actions } = useContext(DialogContext); - const children = render({ hide: () => actions.hide(id) }); - return ( - { - onClose?.(); - actions.hide(id); - }} - {...props} - > - {children} - - ); -} - -export const useDialog = () => useContext(DialogContext).actions; - -export function Dialogs() { - const { dialogs } = useContext(DialogContext); - return ( - <> - {dialogs.map((props: DialogEntry) => ( - - ))} - - ); -} +export const DialogContext = createContext({} as DialogState); diff --git a/src-web/components/Dialogs.tsx b/src-web/components/Dialogs.tsx new file mode 100644 index 00000000..f81922ba --- /dev/null +++ b/src-web/components/Dialogs.tsx @@ -0,0 +1,75 @@ +import React, { useContext, useMemo, useState } from 'react'; +import { trackEvent } from '../lib/analytics'; +import { Dialog, type DialogProps } from './core/Dialog'; +import { DialogContext } from './DialogContext'; + +type DialogEntry = { + id: string; + render: ({ hide }: { hide: () => void }) => React.ReactNode; +} & Omit; + +export interface DialogState { + dialogs: DialogEntry[]; + actions: Actions; +} + +interface Actions { + show: (d: DialogEntry) => void; + toggle: (d: DialogEntry) => void; + hide: (id: string) => void; +} + +export const DialogProvider = ({ children }: { children: React.ReactNode }) => { + const [dialogs, setDialogs] = useState([]); + const actions = useMemo( + () => ({ + show({ id, ...props }: DialogEntry) { + trackEvent('dialog', 'show', { id }); + setDialogs((a) => [...a.filter((d) => d.id !== id), { id, ...props }]); + }, + toggle({ id, ...props }: DialogEntry) { + if (dialogs.some((d) => d.id === id)) this.hide(id); + else this.show({ id, ...props }); + }, + hide: (id: string) => { + setDialogs((a) => a.filter((d) => d.id !== id)); + }, + }), + [dialogs], + ); + + const state: DialogState = { + dialogs, + actions, + }; + + return {children}; +}; + +function DialogInstance({ id, render, onClose, ...props }: DialogEntry) { + const { actions } = useContext(DialogContext); + const children = render({ hide: () => actions.hide(id) }); + return ( + { + onClose?.(); + actions.hide(id); + }} + {...props} + > + {children} + + ); +} + +export function Dialogs() { + const { dialogs } = useContext(DialogContext); + return ( + <> + {dialogs.map((props: DialogEntry) => ( + + ))} + + ); +} diff --git a/src-web/components/EnvironmentActionsDropdown.tsx b/src-web/components/EnvironmentActionsDropdown.tsx index 98a3446b..81fae1b8 100644 --- a/src-web/components/EnvironmentActionsDropdown.tsx +++ b/src-web/components/EnvironmentActionsDropdown.tsx @@ -8,7 +8,7 @@ import { Button } from './core/Button'; import type { DropdownItem } from './core/Dropdown'; import { Dropdown } from './core/Dropdown'; import { Icon } from './core/Icon'; -import { useDialog } from './DialogContext'; +import { useDialog } from '../hooks/useDialog'; import { EnvironmentEditDialog } from './EnvironmentEditDialog'; type Props = { diff --git a/src-web/components/GraphQLEditor.tsx b/src-web/components/GraphQLEditor.tsx index 0d9227cf..88a25c31 100644 --- a/src-web/components/GraphQLEditor.tsx +++ b/src-web/components/GraphQLEditor.tsx @@ -1,18 +1,20 @@ import type { HttpRequest } from '@yaakapp-internal/models'; import { updateSchema } from 'cm6-graphql'; import type { EditorView } from 'codemirror'; + +import { formatSdl } from 'format-graphql'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useLocalStorage } from 'react-use'; import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL'; import { tryFormatJson } from '../lib/formatters'; import { Button } from './core/Button'; import { Dropdown } from './core/Dropdown'; -import type { EditorProps } from './core/Editor'; -import { Editor, formatGraphQL } from './core/Editor'; +import type { EditorProps } from './core/Editor/Editor'; +import { Editor } from './core/Editor/Editor'; import { FormattedError } from './core/FormattedError'; import { Icon } from './core/Icon'; import { Separator } from './core/Separator'; -import { useDialog } from './DialogContext'; +import { useDialog } from '../hooks/useDialog'; type Props = Pick & { baseRequest: HttpRequest; @@ -168,7 +170,7 @@ export function GraphQLEditor({ body, onChange, baseRequest, ...extraEditorProps & { services: ReflectResponseService[] | null; diff --git a/src-web/components/HeaderSize.tsx b/src-web/components/HeaderSize.tsx index aab3d067..d99b17eb 100644 --- a/src-web/components/HeaderSize.tsx +++ b/src-web/components/HeaderSize.tsx @@ -1,10 +1,11 @@ import classNames from 'classnames'; import type { HTMLAttributes, ReactNode } from 'react'; import React from 'react'; -import { useSettings } from '../hooks/useSettings'; import { useOsInfo } from '../hooks/useOsInfo'; +import { useSettings } from '../hooks/useSettings'; import { useStoplightsVisible } from '../hooks/useStoplightsVisible'; -import { WINDOW_CONTROLS_WIDTH, WindowControls } from './WindowControls'; +import { HEADER_SIZE_LG, HEADER_SIZE_MD, WINDOW_CONTROLS_WIDTH } from '../lib/constants'; +import { WindowControls } from './WindowControls'; interface HeaderSizeProps extends HTMLAttributes { children?: ReactNode; @@ -13,9 +14,6 @@ interface HeaderSizeProps extends HTMLAttributes { onlyXWindowControl?: boolean; } -export const HEADER_SIZE_MD = '27px'; -export const HEADER_SIZE_LG = '38px'; - export function HeaderSize({ className, style, @@ -33,7 +31,8 @@ export function HeaderSize({ style={{ ...style, // Add padding for macOS stoplights, but keep it the same width (account for the interface scale) - paddingLeft: (stoplightsVisible && !ignoreControlsSpacing) ? 72 / settings.interfaceScale : undefined, + paddingLeft: + stoplightsVisible && !ignoreControlsSpacing ? 72 / settings.interfaceScale : undefined, ...(size === 'md' ? { height: HEADER_SIZE_MD } : {}), ...(size === 'lg' ? { height: HEADER_SIZE_LG } : {}), ...(osInfo.osType === 'macos' || ignoreControlsSpacing diff --git a/src-web/components/LicenseBadge.tsx b/src-web/components/LicenseBadge.tsx index 7712eaa7..a9ee9126 100644 --- a/src-web/components/LicenseBadge.tsx +++ b/src-web/components/LicenseBadge.tsx @@ -3,7 +3,7 @@ import { useLicense } from '@yaakapp-internal/license'; import { useOpenSettings } from '../hooks/useOpenSettings'; import type { ButtonProps } from './core/Button'; import { Button } from './core/Button'; -import { SettingsTab } from './Settings/Settings'; +import {SettingsTab} from "./Settings/SettingsTab"; const details: Record< LicenseCheckStatus['type'], diff --git a/src-web/components/MarkdownEditor.tsx b/src-web/components/MarkdownEditor.tsx index 455b7c93..8d5f22d5 100644 --- a/src-web/components/MarkdownEditor.tsx +++ b/src-web/components/MarkdownEditor.tsx @@ -4,7 +4,7 @@ import { useRef } from 'react'; import Markdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { useKeyValue } from '../hooks/useKeyValue'; -import { Editor } from './core/Editor'; +import {Editor} from "./core/Editor/Editor"; import { IconButton } from './core/IconButton'; import { SplitLayout } from './core/SplitLayout'; import { VStack } from './core/Stacks'; diff --git a/src-web/components/MoveToWorkspaceDialog.tsx b/src-web/components/MoveToWorkspaceDialog.tsx index d36a3599..1846566e 100644 --- a/src-web/components/MoveToWorkspaceDialog.tsx +++ b/src-web/components/MoveToWorkspaceDialog.tsx @@ -1,16 +1,15 @@ +import { useNavigate } from '@tanstack/react-router'; import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models'; import React, { useState } from 'react'; +import { useToast } from '../hooks/useToast'; import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest'; import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest'; import { useWorkspaces } from '../hooks/useWorkspaces'; import { fallbackRequestName } from '../lib/fallbackRequestName'; -import { router } from '../main'; -import { Route } from '../routes/workspaces/$workspaceId/index'; import { Button } from './core/Button'; import { InlineCode } from './core/InlineCode'; import { Select } from './core/Select'; import { VStack } from './core/Stacks'; -import { useToast } from './ToastContext'; interface Props { activeWorkspaceId: string; @@ -23,6 +22,7 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr const updateHttpRequest = useUpdateAnyHttpRequest(); const updateGrpcRequest = useUpdateAnyGrpcRequest(); const toast = useToast(); + const navigate = useNavigate(); const [selectedWorkspaceId, setSelectedWorkspaceId] = useState(activeWorkspaceId); return ( @@ -69,10 +69,10 @@ export function MoveToWorkspaceDialog({ onDone, request, activeWorkspaceId }: Pr size="xs" color="secondary" className="mr-auto min-w-[5rem]" - onClick={() => { + onClick={async () => { toast.hide('workspace-moved'); - router.navigate({ - to: Route.fullPath, + await navigate({ + to: '/workspaces/$workspaceId', params: { workspaceId: selectedWorkspaceId }, }); }} diff --git a/src-web/components/RecentRequestsDropdown.tsx b/src-web/components/RecentRequestsDropdown.tsx index 85f14248..b06881a4 100644 --- a/src-web/components/RecentRequestsDropdown.tsx +++ b/src-web/components/RecentRequestsDropdown.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from '@tanstack/react-router'; import classNames from 'classnames'; import { useMemo, useRef } from 'react'; import { useKeyPressEvent } from 'react-use'; @@ -7,8 +8,6 @@ import { useHotKey } from '../hooks/useHotKey'; import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRequests } from '../hooks/useRequests'; import { fallbackRequestName } from '../lib/fallbackRequestName'; -import { router } from '../main'; -import { Route } from '../routes/workspaces/$workspaceId/requests/$requestId'; import type { ButtonProps } from './core/Button'; import { Button } from './core/Button'; import type { DropdownItem, DropdownRef } from './core/Dropdown'; @@ -22,6 +21,7 @@ export function RecentRequestsDropdown({ className }: Pick allRecentRequestIds.slice(1), [allRecentRequestIds]); const requests = useRequests(); + const navigate = useNavigate(); // Handle key-up useKeyPressEvent('Control', undefined, () => { @@ -52,9 +52,9 @@ export function RecentRequestsDropdown({ className }: Pick, leftSlot: , - onSelect: () => { - router.navigate({ - to: Route.fullPath, + onSelect: async () => { + await navigate({ + to: '/workspaces/$workspaceId/requests/$requestId', params: { requestId: request.id, workspaceId: activeWorkspace.id, @@ -77,7 +77,7 @@ export function RecentRequestsDropdown({ className }: Pick diff --git a/src-web/components/RedirectToLatestWorkspace.tsx b/src-web/components/RedirectToLatestWorkspace.tsx index 1f5a8f1d..b9326d7d 100644 --- a/src-web/components/RedirectToLatestWorkspace.tsx +++ b/src-web/components/RedirectToLatestWorkspace.tsx @@ -1,16 +1,15 @@ +import { useNavigate } from '@tanstack/react-router'; import { useEffect } from 'react'; import { getRecentCookieJars } from '../hooks/useRecentCookieJars'; import { getRecentEnvironments } from '../hooks/useRecentEnvironments'; import { getRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; import { useWorkspaces } from '../hooks/useWorkspaces'; -import { router } from '../main'; -import { Route as WorkspaceRoute } from '../routes/workspaces/$workspaceId'; -import { Route as RequestRoute } from '../routes/workspaces/$workspaceId/requests/$requestId'; export function RedirectToLatestWorkspace() { const workspaces = useWorkspaces(); const recentWorkspaces = useRecentWorkspaces(); + const navigate = useNavigate(); useEffect(() => { if (workspaces.length === 0) { @@ -25,20 +24,20 @@ export function RedirectToLatestWorkspace() { const requestId = (await getRecentRequests(workspaceId))[0] ?? null; if (workspaceId != null && requestId != null) { - await router.navigate({ - to: RequestRoute.fullPath, + await navigate({ + to: '/workspaces/$workspaceId/requests/$requestId', params: { workspaceId, requestId }, search: { cookieJarId, environmentId }, }); } else { - await router.navigate({ - to: WorkspaceRoute.fullPath, + await navigate({ + to: '/workspaces/$workspaceId', params: { workspaceId }, search: { cookieJarId, environmentId }, }); } })(); - }, [recentWorkspaces, workspaces, workspaces.length]); + }, [navigate, recentWorkspaces, workspaces, workspaces.length]); return <>; } diff --git a/src-web/components/RequestContextMenu.tsx b/src-web/components/RequestContextMenu.tsx index 0cfd3348..a620e605 100644 --- a/src-web/components/RequestContextMenu.tsx +++ b/src-web/components/RequestContextMenu.tsx @@ -15,7 +15,7 @@ import { getHttpRequest } from '../lib/store'; import type { DropdownItem } from './core/Dropdown'; import { ContextMenu } from './core/Dropdown'; import { Icon } from './core/Icon'; -import { useDialog } from './DialogContext'; +import { useDialog } from '../hooks/useDialog'; import { FolderSettingsDialog } from './FolderSettingsDialog'; import type { SidebarTreeNode } from './Sidebar'; diff --git a/src-web/components/RequestPane.tsx b/src-web/components/RequestPane.tsx index 4e138032..c23a7bfd 100644 --- a/src-web/components/RequestPane.tsx +++ b/src-web/components/RequestPane.tsx @@ -13,6 +13,7 @@ import { useRequestEditor, useRequestEditorEvent } from '../hooks/useRequestEdit import { useRequests } from '../hooks/useRequests'; import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey'; import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; +import { useToast } from '../hooks/useToast'; import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest'; import { languageFromContentType } from '../lib/contentType'; import { fallbackRequestName } from '../lib/fallbackRequestName'; @@ -34,7 +35,7 @@ import { BasicAuth } from './BasicAuth'; import { BearerAuth } from './BearerAuth'; import { BinaryFileEditor } from './BinaryFileEditor'; import { CountBadge } from './core/CountBadge'; -import { Editor } from './core/Editor'; +import { Editor } from './core/Editor/Editor'; import type { GenericCompletionConfig, GenericCompletionOption, @@ -50,7 +51,6 @@ import { FormUrlencodedEditor } from './FormUrlencodedEditor'; import { GraphQLEditor } from './GraphQLEditor'; import { HeadersEditor } from './HeadersEditor'; import { MarkdownEditor } from './MarkdownEditor'; -import { useToast } from './ToastContext'; import { UrlBar } from './UrlBar'; import { UrlParametersEditor } from './UrlParameterEditor'; @@ -446,25 +446,28 @@ export const RequestPane = memo(function RequestPane({ Empty Body )} -
- updateRequest.mutate({ id: activeRequestId, update: { name } })} - /> - - updateRequest.mutate({ id: activeRequestId, update: { description } }) - } - /> -
+ +
+ + updateRequest.mutate({ id: activeRequestId, update: { name } }) + } + /> + + updateRequest.mutate({ id: activeRequestId, update: { description } }) + } + /> +
diff --git a/src-web/components/RouteError.tsx b/src-web/components/RouteError.tsx index 7c034d04..9568a2e8 100644 --- a/src-web/components/RouteError.tsx +++ b/src-web/components/RouteError.tsx @@ -1,12 +1,12 @@ +import { useNavigate } from '@tanstack/react-router'; import { useRouteError } from 'react-router-dom'; -import { router } from '../main'; -import { Route } from '../routes/workspaces'; import { Button } from './core/Button'; import { FormattedError } from './core/FormattedError'; import { Heading } from './core/Heading'; import { VStack } from './core/Stacks'; export default function RouteError() { + const navigate = useNavigate(); const error = useRouteError(); console.log('Error', error); const stringified = JSON.stringify(error); @@ -20,8 +20,8 @@ export default function RouteError() {