mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 09:48:28 +02:00
Separate active tabs per request
This commit is contained in:
@@ -60,6 +60,7 @@ const TAB_BODY = 'body';
|
|||||||
const TAB_PARAMS = 'params';
|
const TAB_PARAMS = 'params';
|
||||||
const TAB_HEADERS = 'headers';
|
const TAB_HEADERS = 'headers';
|
||||||
const TAB_AUTH = 'auth';
|
const TAB_AUTH = 'auth';
|
||||||
|
|
||||||
const DEFAULT_TAB = TAB_BODY;
|
const DEFAULT_TAB = TAB_BODY;
|
||||||
|
|
||||||
export const RequestPane = memo(function RequestPane({
|
export const RequestPane = memo(function RequestPane({
|
||||||
@@ -108,12 +109,7 @@ export const RequestPane = memo(function RequestPane({
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
items[index]!.readOnlyName = true;
|
items[index]!.readOnlyName = true;
|
||||||
} else {
|
} else {
|
||||||
items.push({
|
items.push({ name, value: '', enabled: true, readOnlyName: true });
|
||||||
name,
|
|
||||||
value: '',
|
|
||||||
enabled: true,
|
|
||||||
readOnlyName: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { urlParameterPairs: items, urlParametersKey: placeholderNames.join(',') };
|
return { urlParameterPairs: items, urlParametersKey: placeholderNames.join(',') };
|
||||||
@@ -358,13 +354,14 @@ export const RequestPane = memo(function RequestPane({
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
key={activeRequest.id} // Freshen tabs on request change
|
||||||
value={activeTab}
|
value={activeTab}
|
||||||
label="Request"
|
label="Request"
|
||||||
onChangeValue={setActiveTab}
|
onChangeValue={setActiveTab}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
tabListClassName="mt-2 !mb-1.5"
|
tabListClassName="mt-2 !mb-1.5"
|
||||||
>
|
>
|
||||||
<TabContent value="auth">
|
<TabContent value={TAB_AUTH}>
|
||||||
{activeRequest.authenticationType === AUTH_TYPE_BASIC ? (
|
{activeRequest.authenticationType === AUTH_TYPE_BASIC ? (
|
||||||
<BasicAuth key={forceUpdateKey} request={activeRequest} />
|
<BasicAuth key={forceUpdateKey} request={activeRequest} />
|
||||||
) : activeRequest.authenticationType === AUTH_TYPE_BEARER ? (
|
) : activeRequest.authenticationType === AUTH_TYPE_BEARER ? (
|
||||||
@@ -375,21 +372,21 @@ export const RequestPane = memo(function RequestPane({
|
|||||||
</EmptyStateText>
|
</EmptyStateText>
|
||||||
)}
|
)}
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="headers">
|
<TabContent value={TAB_HEADERS}>
|
||||||
<HeadersEditor
|
<HeadersEditor
|
||||||
forceUpdateKey={`${forceUpdateHeaderEditorKey}::${forceUpdateKey}`}
|
forceUpdateKey={`${forceUpdateHeaderEditorKey}::${forceUpdateKey}`}
|
||||||
headers={activeRequest.headers}
|
headers={activeRequest.headers}
|
||||||
onChange={handleHeadersChange}
|
onChange={handleHeadersChange}
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="params">
|
<TabContent value={TAB_PARAMS}>
|
||||||
<UrlParametersEditor
|
<UrlParametersEditor
|
||||||
forceUpdateKey={forceUpdateKey + urlParametersKey}
|
forceUpdateKey={forceUpdateKey + urlParametersKey}
|
||||||
pairs={urlParameterPairs}
|
pairs={urlParameterPairs}
|
||||||
onChange={handleUrlParametersChange}
|
onChange={handleUrlParametersChange}
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="body">
|
<TabContent value={TAB_BODY}>
|
||||||
{activeRequest.bodyType === BODY_TYPE_JSON ? (
|
{activeRequest.bodyType === BODY_TYPE_JSON ? (
|
||||||
<Editor
|
<Editor
|
||||||
forceUpdateKey={forceUpdateKey}
|
forceUpdateKey={forceUpdateKey}
|
||||||
|
|||||||
@@ -154,20 +154,15 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ
|
|||||||
</Banner>
|
</Banner>
|
||||||
) : (
|
) : (
|
||||||
<Tabs
|
<Tabs
|
||||||
|
key={activeRequest.id} // Freshen tabs on request change
|
||||||
value={activeTab}
|
value={activeTab}
|
||||||
onChangeValue={setActiveTab}
|
onChangeValue={setActiveTab}
|
||||||
label="Response"
|
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
|
label="Response"
|
||||||
className="ml-3 mr-3 mb-3"
|
className="ml-3 mr-3 mb-3"
|
||||||
tabListClassName="mt-1.5"
|
tabListClassName="mt-1.5"
|
||||||
>
|
>
|
||||||
<TabContent value="headers">
|
<TabContent value={TAB_BODY}>
|
||||||
<ResponseHeaders response={activeResponse} />
|
|
||||||
</TabContent>
|
|
||||||
<TabContent value="info">
|
|
||||||
<ResponseInfo response={activeResponse} />
|
|
||||||
</TabContent>
|
|
||||||
<TabContent value="body">
|
|
||||||
{!activeResponse.contentLength ? (
|
{!activeResponse.contentLength ? (
|
||||||
<div className="pb-2 h-full">
|
<div className="pb-2 h-full">
|
||||||
<EmptyStateText>Empty Body</EmptyStateText>
|
<EmptyStateText>Empty Body</EmptyStateText>
|
||||||
@@ -192,6 +187,12 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</TabContent>
|
</TabContent>
|
||||||
|
<TabContent value={TAB_HEADERS}>
|
||||||
|
<ResponseHeaders response={activeResponse} />
|
||||||
|
</TabContent>
|
||||||
|
<TabContent value={TAB_INFO}>
|
||||||
|
<ResponseInfo response={activeResponse} />
|
||||||
|
</TabContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { memo, useCallback, useRef } from 'react';
|
import { memo, useEffect, useRef } from 'react';
|
||||||
import { Icon } from '../Icon';
|
import { Icon } from '../Icon';
|
||||||
import type { RadioDropdownProps } from '../RadioDropdown';
|
import type { RadioDropdownProps } from '../RadioDropdown';
|
||||||
import { RadioDropdown } from '../RadioDropdown';
|
import { RadioDropdown } from '../RadioDropdown';
|
||||||
@@ -39,26 +39,23 @@ export function Tabs({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const handleTabChange = useCallback(
|
// Update tabs when value changes
|
||||||
(value: string) => {
|
useEffect(() => {
|
||||||
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
|
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
|
||||||
for (const tab of tabs ?? []) {
|
for (const tab of tabs ?? []) {
|
||||||
const v = tab.getAttribute('data-tab');
|
const v = tab.getAttribute('data-tab');
|
||||||
if (v === value) {
|
if (v === value) {
|
||||||
tab.setAttribute('tabindex', '-1');
|
tab.setAttribute('tabindex', '-1');
|
||||||
tab.setAttribute('data-state', 'active');
|
tab.setAttribute('data-state', 'active');
|
||||||
tab.setAttribute('aria-hidden', 'false');
|
tab.setAttribute('aria-hidden', 'false');
|
||||||
tab.style.display = 'block';
|
tab.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
tab.setAttribute('data-state', 'inactive');
|
tab.setAttribute('data-state', 'inactive');
|
||||||
tab.setAttribute('aria-hidden', 'true');
|
tab.setAttribute('aria-hidden', 'true');
|
||||||
tab.style.display = 'none';
|
tab.style.display = 'none';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onChangeValue(value);
|
}
|
||||||
},
|
}, [value]);
|
||||||
[onChangeValue],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -98,7 +95,7 @@ export function Tabs({
|
|||||||
onChange={t.options.onChange}
|
onChange={t.options.onChange}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={isActive ? undefined : () => handleTabChange(t.value)}
|
onClick={isActive ? undefined : () => onChangeValue(t.value)}
|
||||||
className={btnClassName}
|
className={btnClassName}
|
||||||
>
|
>
|
||||||
{option && 'shortLabel' in option
|
{option && 'shortLabel' in option
|
||||||
@@ -116,7 +113,7 @@ export function Tabs({
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={t.value}
|
key={t.value}
|
||||||
onClick={() => handleTabChange(t.value)}
|
onClick={() => onChangeValue(t.value)}
|
||||||
className={btnClassName}
|
className={btnClassName}
|
||||||
>
|
>
|
||||||
{t.label}
|
{t.label}
|
||||||
|
|||||||
Reference in New Issue
Block a user