feat: persist window frames and widths (#7409)

This commit is contained in:
shubh-bruno
2026-03-26 13:11:04 +05:30
committed by GitHub
parent 304f6c8b80
commit 73df422c4e
37 changed files with 766 additions and 133 deletions

View File

@@ -1,8 +1,9 @@
import React, { useState, useMemo, useCallback } from 'react';
import { get } from 'lodash';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import { updateResponseExampleFileBodyParams } from 'providers/ReduxStore/slices/collections';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import mime from 'mime-types';
import path from 'utils/common/path';
import EditableTable from 'components/EditableTable';
@@ -14,6 +15,16 @@ import RadioButton from 'components/RadioButton';
const ResponseExampleFileBody = ({ item, collection, exampleUid, editMode = false }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const fileBodyWidths = focusedTab?.tableColumnWidths?.['example-file-body'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
// Get file data from the specific example
const params = useMemo(() => {
@@ -180,6 +191,9 @@ const ResponseExampleFileBody = ({ item, collection, exampleUid, editMode = fals
return (
<StyledWrapper className="w-full mt-4">
<EditableTable
tableId="example-file-body"
columnWidths={fileBodyWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-file-body', widths)}
columns={columns}
rows={params || []}
onChange={handleParamsChange}

View File

@@ -1,8 +1,9 @@
import React, { useMemo, useCallback } from 'react';
import get from 'lodash/get';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import { updateResponseExampleFormUrlEncodedParams } from 'providers/ReduxStore/slices/collections';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import EditableTable from 'components/EditableTable';
import MultiLineEditor from 'components/MultiLineEditor';
import StyledWrapper from './StyledWrapper';
@@ -10,6 +11,16 @@ import StyledWrapper from './StyledWrapper';
const ResponseExampleFormUrlEncodedParams = ({ item, collection, exampleUid, editMode = false }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const formUrlEncodedWidths = focusedTab?.tableColumnWidths?.['example-form-url-encoded'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
const params = useMemo(() => {
return item.draft
@@ -87,6 +98,9 @@ const ResponseExampleFormUrlEncodedParams = ({ item, collection, exampleUid, edi
return (
<StyledWrapper className="w-full mt-4">
<EditableTable
tableId="example-form-url-encoded"
columnWidths={formUrlEncodedWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-form-url-encoded', widths)}
columns={columns}
rows={params || []}
onChange={handleParamsChange}

View File

@@ -1,8 +1,9 @@
import React, { useState, useMemo, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import get from 'lodash/get';
import { moveResponseExampleRequestHeader, setResponseExampleRequestHeaders } from 'providers/ReduxStore/slices/collections';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import EditableTable from 'components/EditableTable';
import SingleLineEditor from 'components/SingleLineEditor';
import BulkEditor from 'components/BulkEditor';
@@ -15,8 +16,18 @@ const headerAutoCompleteList = StandardHTTPHeaders.map((e) => e.header);
const ResponseExampleHeaders = ({ editMode, item, collection, exampleUid }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
const [isBulkEditMode, setIsBulkEditMode] = useState(false);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const exampleHeadersWidths = focusedTab?.tableColumnWidths?.['example-headers'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
const headers = useMemo(() => {
return item.draft
? get(item, 'draft.examples', []).find((e) => e.uid === exampleUid)?.request?.headers || []
@@ -132,6 +143,9 @@ const ResponseExampleHeaders = ({ editMode, item, collection, exampleUid }) => {
<StyledWrapper className="w-full mt-4">
<div className="mb-3 title text-xs font-bold">Headers</div>
<EditableTable
tableId="example-headers"
columnWidths={exampleHeadersWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-headers', widths)}
columns={columns}
rows={headers || []}
onChange={handleHeadersChange}

View File

@@ -1,10 +1,11 @@
import React, { useMemo, useCallback } from 'react';
import get from 'lodash/get';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import { IconUpload, IconX, IconFile } from '@tabler/icons';
import { updateResponseExampleMultipartFormParams } from 'providers/ReduxStore/slices/collections';
import { browseFiles } from 'providers/ReduxStore/slices/collections/actions';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import mime from 'mime-types';
import path from 'utils/common/path';
import EditableTable from 'components/EditableTable';
@@ -16,6 +17,16 @@ import { isWindowsOS } from 'utils/common/platform';
const ResponseExampleMultipartFormParams = ({ item, collection, exampleUid, editMode = false }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const multipartFormWidths = focusedTab?.tableColumnWidths?.['example-multipart-form'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
const params = useMemo(() => {
return item.draft
@@ -258,6 +269,9 @@ const ResponseExampleMultipartFormParams = ({ item, collection, exampleUid, edit
return (
<StyledWrapper className="w-full mt-4">
<EditableTable
tableId="example-multipart-form"
columnWidths={multipartFormWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-multipart-form', widths)}
columns={columns}
rows={params || []}
onChange={handleParamsChange}

View File

@@ -1,8 +1,9 @@
import React, { useState, useMemo, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import get from 'lodash/get';
import { moveResponseExampleParam, setResponseExampleParams } from 'providers/ReduxStore/slices/collections';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import EditableTable from 'components/EditableTable';
import SingleLineEditor from 'components/SingleLineEditor';
import BulkEditor from 'components/BulkEditor';
@@ -12,8 +13,19 @@ import StyledWrapper from './StyledWrapper';
const ResponseExampleParams = ({ editMode, item, collection, exampleUid }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
const [isBulkEditMode, setIsBulkEditMode] = useState(false);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const exampleQueryParamsWidths = focusedTab?.tableColumnWidths?.['example-query-params'] || {};
const examplePathParamsWidths = focusedTab?.tableColumnWidths?.['example-path-params'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
const params = useMemo(() => {
return item.draft
? get(item, 'draft.examples', []).find((e) => e.uid === exampleUid)?.request?.params || []
@@ -185,6 +197,7 @@ const ResponseExampleParams = ({ editMode, item, collection, exampleUid }) => {
<StyledWrapper className="w-full mt-4">
<div className="mb-3 title text-xs font-bold">Query parameters</div>
<EditableTable
tableId="example-query-params"
columns={queryColumns}
rows={queryParams || []}
onChange={handleQueryParamsChange}
@@ -194,6 +207,8 @@ const ResponseExampleParams = ({ editMode, item, collection, exampleUid }) => {
showAddRow={editMode}
showDelete={editMode}
disableCheckbox={!editMode}
columnWidths={exampleQueryParamsWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-query-params', widths)}
/>
{editMode && (
<div className="flex justify-end mt-2">
@@ -221,6 +236,7 @@ const ResponseExampleParams = ({ editMode, item, collection, exampleUid }) => {
</InfoTip>
</div>
<EditableTable
tableId="example-path-params"
columns={pathColumns}
rows={pathParams}
onChange={handlePathParamsChange}
@@ -229,6 +245,8 @@ const ResponseExampleParams = ({ editMode, item, collection, exampleUid }) => {
showDelete={false}
showAddRow={false}
reorderable={false}
columnWidths={examplePathParamsWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-path-params', widths)}
/>
</>
)}

View File

@@ -1,8 +1,9 @@
import React, { useState, useMemo, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useTheme } from 'providers/Theme';
import get from 'lodash/get';
import { moveResponseExampleHeader, setResponseExampleHeaders, updateResponseExampleResponse } from 'providers/ReduxStore/slices/collections';
import { updateTableColumnWidths } from 'providers/ReduxStore/slices/tabs';
import { getBodyType } from 'utils/responseBodyProcessor';
import EditableTable from 'components/EditableTable';
import SingleLineEditor from 'components/SingleLineEditor';
@@ -16,8 +17,18 @@ const headerAutoCompleteList = StandardHTTPHeaders.map((e) => e.header);
const ResponseExampleResponseHeaders = ({ editMode, item, collection, exampleUid }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
const [isBulkEditMode, setIsBulkEditMode] = useState(false);
// Get column widths from Redux
const focusedTab = tabs?.find((t) => t.uid === activeTabUid);
const responseHeadersWidths = focusedTab?.tableColumnWidths?.['example-response-headers'] || {};
const handleColumnWidthsChange = (tableId, widths) => {
dispatch(updateTableColumnWidths({ uid: activeTabUid, tableId, widths }));
};
const headers = useMemo(() => {
return item.draft ? get(item, 'draft.examples', []).find((e) => e.uid === exampleUid)?.response?.headers || [] : get(item, 'examples', []).find((e) => e.uid === exampleUid)?.response?.headers || [];
}, [item, exampleUid]);
@@ -170,6 +181,9 @@ const ResponseExampleResponseHeaders = ({ editMode, item, collection, exampleUid
return (
<StyledWrapper className="w-full px-4">
<EditableTable
tableId="example-response-headers"
columnWidths={responseHeadersWidths}
onColumnWidthsChange={(widths) => handleColumnWidthsChange('example-response-headers', widths)}
columns={columns}
rows={headers || []}
onChange={handleHeadersChange}