mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Improve export modal UX (#6978)
* improve styles for export modal * fix e2e test
This commit is contained in:
parent
e20c257260
commit
20491d9728
@ -21,7 +21,6 @@ test('can send requests', async ({ app, page }) => {
|
||||
|
||||
await page.getByRole('button', { name: 'Workspace actions menu button' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Export' }).click();
|
||||
await page.getByRole('dialog').getByRole('checkbox').nth(1).uncheck();
|
||||
await page.getByRole('button', { name: 'Export' }).click();
|
||||
await page.getByText('Which format would you like to export as?').click();
|
||||
await page.locator('.app').press('Escape');
|
||||
|
@ -203,7 +203,7 @@ export const WorkspaceCardDropdown: FC<Props> = props => {
|
||||
{isExportModalOpen && (
|
||||
<ExportRequestsModal
|
||||
workspace={workspace}
|
||||
onHide={() => setIsExportModalOpen(false)}
|
||||
onClose={() => setIsExportModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{isSettingsModalOpen && (
|
||||
|
@ -251,7 +251,7 @@ export const WorkspaceDropdown: FC = () => {
|
||||
{isExportModalOpen && (
|
||||
<ExportRequestsModal
|
||||
workspace={activeWorkspace}
|
||||
onHide={() => setIsExportModalOpen(false)}
|
||||
onClose={() => setIsExportModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{isSettingsModalOpen && (
|
||||
|
@ -1,58 +0,0 @@
|
||||
import classnames from 'classnames';
|
||||
import React, { FC, ReactNode, useRef } from 'react';
|
||||
|
||||
import type { RequestGroup } from '../../../models/request-group';
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
handleSetRequestGroupCollapsed: (...args: any[]) => any;
|
||||
isCollapsed: boolean;
|
||||
requestGroup: RequestGroup;
|
||||
selectedRequests: number;
|
||||
totalRequests: number;
|
||||
}
|
||||
export const RequestGroupRow: FC<Props> = ({
|
||||
children,
|
||||
handleSetItemSelected,
|
||||
handleSetRequestGroupCollapsed,
|
||||
isCollapsed,
|
||||
requestGroup,
|
||||
selectedRequests,
|
||||
totalRequests,
|
||||
}) => {
|
||||
const isSelected = selectedRequests === totalRequests;
|
||||
const checkboxRef = useRef<HTMLInputElement>(null);
|
||||
if (checkboxRef.current) {
|
||||
// Partial or indeterminate checkbox.
|
||||
checkboxRef.current.indeterminate = selectedRequests > 0 && selectedRequests < totalRequests;
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={requestGroup._id} className="tree__row">
|
||||
<div className="tree__item tree__item--big">
|
||||
<div className="tree__item__checkbox tree__indent">
|
||||
<input
|
||||
ref={checkboxRef}
|
||||
type="checkbox"
|
||||
checked={isSelected}
|
||||
onChange={e => handleSetItemSelected(requestGroup._id, e.currentTarget.checked)}
|
||||
/>
|
||||
</div>
|
||||
<button onClick={() => handleSetRequestGroupCollapsed(requestGroup._id, !isCollapsed)}>
|
||||
<i className={classnames('tree__item__icon', 'fa', `fa-folder${isCollapsed ? '' : '-open'}`)} />
|
||||
{requestGroup.name}
|
||||
<span className="total-requests">{totalRequests} requests</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul
|
||||
className={classnames('tree__list', {
|
||||
'tree__list--collapsed': isCollapsed,
|
||||
})}
|
||||
>
|
||||
{!isCollapsed ? children : null}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
import React, { FC, SyntheticEvent, useCallback } from 'react';
|
||||
|
||||
import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
|
||||
import { isRequest, Request } from '../../../models/request';
|
||||
import { isWebSocketRequest, WebSocketRequest } from '../../../models/websocket-request';
|
||||
import { GrpcTag } from '../tags/grpc-tag';
|
||||
import { MethodTag } from '../tags/method-tag';
|
||||
import { WebSocketTag } from '../tags/websocket-tag';
|
||||
|
||||
interface Props {
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
isSelected: boolean;
|
||||
request: Request | WebSocketRequest | GrpcRequest;
|
||||
}
|
||||
|
||||
export const RequestRow: FC<Props> = ({
|
||||
handleSetItemSelected,
|
||||
request,
|
||||
isSelected,
|
||||
}) => {
|
||||
const onChange = useCallback((event: SyntheticEvent<HTMLInputElement>) => {
|
||||
handleSetItemSelected(request._id, event?.currentTarget.checked);
|
||||
}, [handleSetItemSelected, request._id]);
|
||||
|
||||
return (
|
||||
<li className="tree__row">
|
||||
<div className="tree__item tree__item--request">
|
||||
<div className="tree__item__checkbox tree__indent">
|
||||
<input type="checkbox" checked={isSelected} onChange={onChange} />
|
||||
</div>
|
||||
<button className="wide">
|
||||
{isRequest(request) ? <MethodTag method={request.method} /> : null}
|
||||
{isGrpcRequest(request) ? <GrpcTag /> : null}
|
||||
{isWebSocketRequest(request) ? <WebSocketTag /> : null}
|
||||
<span className="inline-block">{request.name}</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
@ -1,56 +0,0 @@
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import { isGrpcRequest } from '../../../models/grpc-request';
|
||||
import { isRequest } from '../../../models/request';
|
||||
import { isWebSocketRequest } from '../../../models/websocket-request';
|
||||
import type { Node } from '../modals/export-requests-modal';
|
||||
import { RequestGroupRow } from './request-group-row';
|
||||
import { RequestRow } from './request-row';
|
||||
|
||||
interface Props {
|
||||
root?: Node | null;
|
||||
handleSetRequestGroupCollapsed: (...args: any[]) => any;
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
}
|
||||
|
||||
export const Tree: FC<Props> = ({ root, handleSetRequestGroupCollapsed, handleSetItemSelected }) => {
|
||||
const renderChildren = (node?: Node | null) => {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isRequest(node.doc) || isWebSocketRequest(node.doc) || isGrpcRequest(node.doc)) {
|
||||
return (
|
||||
<RequestRow
|
||||
key={node.doc._id}
|
||||
handleSetItemSelected={handleSetItemSelected}
|
||||
isSelected={node.selectedRequests === node.totalRequests}
|
||||
request={node.doc}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (node.totalRequests === 0) {
|
||||
// Don't show empty folders.
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RequestGroupRow
|
||||
key={node.doc._id}
|
||||
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
|
||||
handleSetItemSelected={handleSetItemSelected}
|
||||
isCollapsed={node.collapsed}
|
||||
totalRequests={node.totalRequests}
|
||||
selectedRequests={node.selectedRequests}
|
||||
requestGroup={node.doc}
|
||||
>
|
||||
{node.children.map(child => renderChildren(child))}
|
||||
</RequestGroupRow>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className="tree__list tree__list-root theme--tree__list">{renderChildren(root)}</ul>
|
||||
);
|
||||
};
|
@ -1,20 +1,17 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { OverlayContainer } from 'react-aria';
|
||||
import React, { FC, ReactNode, useEffect, useState } from 'react';
|
||||
import { Button, Checkbox, Dialog, Heading, Modal, ModalOverlay } from 'react-aria-components';
|
||||
import { useFetcher, useParams } from 'react-router-dom';
|
||||
|
||||
import { exportRequestsToFile } from '../../../common/export';
|
||||
import * as models from '../../../models';
|
||||
import { requestGroup } from '../../../models';
|
||||
import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
|
||||
import { isRequest, Request } from '../../../models/request';
|
||||
import { RequestGroup } from '../../../models/request-group';
|
||||
import { isWebSocketRequest, WebSocketRequest } from '../../../models/websocket-request';
|
||||
import { Workspace } from '../../../models/workspace';
|
||||
import { Child, WorkspaceLoaderData } from '../../routes/workspace';
|
||||
import { Modal, type ModalHandle, ModalProps } from '../base/modal';
|
||||
import { ModalBody } from '../base/modal-body';
|
||||
import { ModalFooter } from '../base/modal-footer';
|
||||
import { ModalHeader } from '../base/modal-header';
|
||||
import { Tree } from '../export-requests/tree';
|
||||
import { Icon } from '../icon';
|
||||
import { getMethodShortHand } from '../tags/method-tag';
|
||||
|
||||
export interface Node {
|
||||
doc: Request | WebSocketRequest | GrpcRequest | RequestGroup;
|
||||
@ -24,15 +21,160 @@ export interface Node {
|
||||
selectedRequests: number;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
treeRoot: Node | null;
|
||||
}
|
||||
export const RequestGroupRow: FC<{
|
||||
children?: ReactNode;
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
handleSetRequestGroupCollapsed: (...args: any[]) => any;
|
||||
isCollapsed: boolean;
|
||||
requestGroup: RequestGroup;
|
||||
selectedRequests: number;
|
||||
totalRequests: number;
|
||||
}> = ({
|
||||
children,
|
||||
handleSetItemSelected,
|
||||
handleSetRequestGroupCollapsed,
|
||||
isCollapsed,
|
||||
requestGroup,
|
||||
selectedRequests,
|
||||
totalRequests,
|
||||
}) => {
|
||||
const isSelected = selectedRequests === totalRequests;
|
||||
const isIndeterminate = selectedRequests > 0 && selectedRequests < totalRequests;
|
||||
|
||||
export const ExportRequestsModal = ({ workspace, onHide }: { workspace: Workspace } & ModalProps) => {
|
||||
const modalRef = useRef<ModalHandle>(null);
|
||||
return (
|
||||
<li key={requestGroup._id} className="flex flex-col">
|
||||
<div className="flex items-center gap-2 p-2">
|
||||
<Checkbox isIndeterminate={isIndeterminate} slot={null} isSelected={isSelected} onChange={isSelected => handleSetItemSelected(requestGroup._id, isSelected)} className="group p-0 flex items-center h-full">
|
||||
<div className="w-4 h-4 rounded flex items-center justify-center transition-colors group-data-[selected]:bg-[--hl-xs] group-focus:ring-2 ring-1 ring-[--hl-sm]">
|
||||
<Icon icon={isIndeterminate ? 'minus' : 'check'} className='opacity-0 group-data-[selected]:opacity-100 group-data-[indeterminate]:opacity-100 group-data-[selected]:text-[--color-success] w-3 h-3' />
|
||||
</div>
|
||||
</Checkbox>
|
||||
<Button className="flex items-center gap-2" onPress={() => handleSetRequestGroupCollapsed(requestGroup._id, !isCollapsed)}>
|
||||
<Icon icon={isCollapsed ? 'folder' : 'folder-open'} />
|
||||
{requestGroup.name}
|
||||
<span className="text-sm text-[--hl]">{totalRequests} requests</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<ul
|
||||
className="flex flex-col pl-5"
|
||||
>
|
||||
{!isCollapsed ? children : null}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export const RequestRow: FC<{
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
isSelected: boolean;
|
||||
request: Request | WebSocketRequest | GrpcRequest;
|
||||
}> = ({
|
||||
handleSetItemSelected,
|
||||
request,
|
||||
isSelected,
|
||||
}) => {
|
||||
return (
|
||||
<li className="flex items-center gap-2 p-2">
|
||||
<Checkbox
|
||||
slot={null}
|
||||
isSelected={isSelected}
|
||||
onChange={isSelected => {
|
||||
handleSetItemSelected(request._id, isSelected);
|
||||
}}
|
||||
className="group p-0 flex items-center h-full"
|
||||
>
|
||||
<div className="w-4 h-4 rounded flex items-center justify-center transition-colors group-data-[selected]:bg-[--hl-xs] group-focus:ring-2 ring-1 ring-[--hl-sm]">
|
||||
<Icon icon='check' className='opacity-0 group-data-[selected]:opacity-100 group-data-[selected]:text-[--color-success] w-3 h-3' />
|
||||
</div>
|
||||
</Checkbox>
|
||||
<div className="w-full flex items-center gap-2">
|
||||
{isRequest(request) && (
|
||||
<span
|
||||
className={
|
||||
`w-10 flex-shrink-0 flex text-[0.65rem] rounded-sm border border-solid border-[--hl-sm] items-center justify-center
|
||||
${{
|
||||
'GET': 'text-[--color-font-surprise] bg-[rgba(var(--color-surprise-rgb),0.5)]',
|
||||
'POST': 'text-[--color-font-success] bg-[rgba(var(--color-success-rgb),0.5)]',
|
||||
'HEAD': 'text-[--color-font-info] bg-[rgba(var(--color-info-rgb),0.5)]',
|
||||
'OPTIONS': 'text-[--color-font-info] bg-[rgba(var(--color-info-rgb),0.5)]',
|
||||
'DELETE': 'text-[--color-font-danger] bg-[rgba(var(--color-danger-rgb),0.5)]',
|
||||
'PUT': 'text-[--color-font-warning] bg-[rgba(var(--color-warning-rgb),0.5)]',
|
||||
'PATCH': 'text-[--color-font-notice] bg-[rgba(var(--color-notice-rgb),0.5)]',
|
||||
}[request.method] || 'text-[--color-font] bg-[--hl-md]'}`
|
||||
}
|
||||
>
|
||||
{getMethodShortHand(request)}
|
||||
</span>
|
||||
)}
|
||||
{isWebSocketRequest(request) && (
|
||||
<span className="w-10 flex-shrink-0 flex text-[0.65rem] rounded-sm border border-solid border-[--hl-sm] items-center justify-center text-[--color-font-notice] bg-[rgba(var(--color-notice-rgb),0.5)]">
|
||||
WS
|
||||
</span>
|
||||
)}
|
||||
{isGrpcRequest(request) && (
|
||||
<span className="w-10 flex-shrink-0 flex text-[0.65rem] rounded-sm border border-solid border-[--hl-sm] items-center justify-center text-[--color-font-info] bg-[rgba(var(--color-info-rgb),0.5)]">
|
||||
gRPC
|
||||
</span>
|
||||
)}
|
||||
<span>{request.name}</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export const Tree: FC<{
|
||||
root?: Node | null;
|
||||
handleSetRequestGroupCollapsed: (...args: any[]) => any;
|
||||
handleSetItemSelected: (...args: any[]) => any;
|
||||
}> = ({ root, handleSetRequestGroupCollapsed, handleSetItemSelected }) => {
|
||||
const renderChildren = (node?: Node | null) => {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isRequest(node.doc) || isWebSocketRequest(node.doc) || isGrpcRequest(node.doc)) {
|
||||
return (
|
||||
<RequestRow
|
||||
key={node.doc._id}
|
||||
handleSetItemSelected={handleSetItemSelected}
|
||||
isSelected={node.selectedRequests === node.totalRequests}
|
||||
request={node.doc}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (node.totalRequests === 0) {
|
||||
// Don't show empty folders.
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RequestGroupRow
|
||||
key={node.doc._id}
|
||||
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
|
||||
handleSetItemSelected={handleSetItemSelected}
|
||||
isCollapsed={node.collapsed}
|
||||
totalRequests={node.totalRequests}
|
||||
selectedRequests={node.selectedRequests}
|
||||
requestGroup={node.doc}
|
||||
>
|
||||
{node.children.map(child => renderChildren(child))}
|
||||
</RequestGroupRow>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className="flex flex-col">{renderChildren(root)}</ul>
|
||||
);
|
||||
};
|
||||
|
||||
export const ExportRequestsModal = ({ workspace, onClose }: { workspace: Workspace; onClose: () => void }) => {
|
||||
const { organizationId, projectId } = useParams() as { organizationId: string; projectId: string };
|
||||
const workspaceFetcher = useFetcher();
|
||||
const [state, setState] = useState<State>();
|
||||
const [state, setState] = useState<{
|
||||
treeRoot: Node | null;
|
||||
}>();
|
||||
|
||||
useEffect(() => {
|
||||
const isIdleAndUninitialized = workspaceFetcher.state === 'idle' && !workspaceFetcher.data;
|
||||
@ -60,9 +202,9 @@ export const ExportRequestsModal = ({ workspace, onHide }: { workspace: Workspac
|
||||
setState({
|
||||
treeRoot: {
|
||||
doc: {
|
||||
...models.requestGroup.init(),
|
||||
...requestGroup.init(),
|
||||
_id: 'all',
|
||||
type: models.requestGroup.type,
|
||||
type: requestGroup.type,
|
||||
name: 'All requests',
|
||||
parentId: '',
|
||||
modified: 0,
|
||||
@ -77,9 +219,10 @@ export const ExportRequestsModal = ({ workspace, onHide }: { workspace: Workspac
|
||||
});
|
||||
}, [workspaceLoaderData?.requestTree]);
|
||||
|
||||
useEffect(() => {
|
||||
modalRef.current?.show();
|
||||
}, []);
|
||||
if (!workspaceLoaderData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getSelectedRequestIds = (node: Node): string[] => {
|
||||
const docIsRequest = isRequest(node.doc) || isWebSocketRequest(node.doc) || isGrpcRequest(node.doc);
|
||||
if (docIsRequest && node.selectedRequests === node.totalRequests) {
|
||||
@ -114,47 +257,73 @@ export const ExportRequestsModal = ({ workspace, onHide }: { workspace: Workspac
|
||||
};
|
||||
|
||||
const isExportDisabled = state?.treeRoot?.selectedRequests === 0 || false;
|
||||
|
||||
return (
|
||||
<OverlayContainer onClick={e => e.stopPropagation()}>
|
||||
<Modal ref={modalRef} tall onHide={onHide}>
|
||||
<ModalHeader>Select Requests to Export</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="requests-tree">
|
||||
<Tree
|
||||
root={state?.treeRoot}
|
||||
handleSetRequestGroupCollapsed={(requestGroupId: string, isCollapsed: boolean) => {
|
||||
if (state?.treeRoot && setRequestGroupCollapsed(state?.treeRoot, isCollapsed, requestGroupId)) {
|
||||
setState({ treeRoot: state?.treeRoot });
|
||||
}
|
||||
}}
|
||||
handleSetItemSelected={(itemId: string, isSelected: boolean) => {
|
||||
if (state?.treeRoot && setItemSelected(state?.treeRoot, isSelected, itemId)) {
|
||||
setState({ treeRoot: state?.treeRoot });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ModalOverlay
|
||||
isOpen
|
||||
onOpenChange={isOpen => {
|
||||
!isOpen && onClose();
|
||||
}}
|
||||
isDismissable
|
||||
className="w-full h-[--visual-viewport-height] fixed z-10 top-0 left-0 flex items-center justify-center bg-black/30"
|
||||
>
|
||||
<Modal
|
||||
onOpenChange={isOpen => {
|
||||
!isOpen && onClose();
|
||||
}}
|
||||
className="flex flex-col max-w-4xl w-full rounded-md border border-solid border-[--hl-sm] p-[--padding-lg] max-h-full bg-[--color-bg] text-[--color-font]"
|
||||
>
|
||||
<Dialog
|
||||
className="outline-none flex-1 h-full flex flex-col overflow-hidden"
|
||||
>
|
||||
{({ close }) => (
|
||||
<div className='flex-1 flex flex-col gap-4 overflow-hidden'>
|
||||
<div className='flex gap-2 items-center justify-between'>
|
||||
<Heading slot="title" className='text-2xl'>Export requests</Heading>
|
||||
<Button
|
||||
className="flex flex-shrink-0 items-center justify-center aspect-square h-6 aria-pressed:bg-[--hl-sm] rounded-sm text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-sm"
|
||||
onPress={close}
|
||||
>
|
||||
<Icon icon="x" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className='rounded w-full border border-solid border-[--hl-sm] select-none overflow-y-auto min-h-[20rem] max-h-96'>
|
||||
<Tree
|
||||
root={state?.treeRoot}
|
||||
handleSetRequestGroupCollapsed={(requestGroupId: string, isCollapsed: boolean) => {
|
||||
if (state?.treeRoot && setRequestGroupCollapsed(state?.treeRoot, isCollapsed, requestGroupId)) {
|
||||
setState({ treeRoot: state?.treeRoot });
|
||||
}
|
||||
}}
|
||||
handleSetItemSelected={(itemId: string, isSelected: boolean) => {
|
||||
if (state?.treeRoot && setItemSelected(state?.treeRoot, isSelected, itemId)) {
|
||||
setState({ treeRoot: state?.treeRoot });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-shrink-0 flex-1 justify-end gap-2 items-center">
|
||||
<Button
|
||||
onPress={close}
|
||||
className="hover:no-underline flex items-center gap-2 hover:bg-opacity-90 border border-solid border-[--hl-md] py-2 px-3 text-[--color-font] transition-colors rounded-sm"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onPress={() => {
|
||||
state?.treeRoot && exportRequestsToFile(getSelectedRequestIds(state.treeRoot));
|
||||
close();
|
||||
}}
|
||||
isDisabled={isExportDisabled}
|
||||
className="hover:no-underline flex items-center gap-2 bg-[--color-surprise] hover:bg-opacity-90 border border-solid border-[--hl-md] py-2 px-3 text-[--color-font-surprise] transition-colors rounded-sm"
|
||||
>
|
||||
<Icon icon="save" /> Export
|
||||
</Button>
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<div>
|
||||
<button className="btn" onClick={() => modalRef.current?.hide()}>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
className="btn"
|
||||
onClick={() => {
|
||||
if (state?.treeRoot && state?.treeRoot.selectedRequests > 0) {
|
||||
exportRequestsToFile(getSelectedRequestIds(state?.treeRoot));
|
||||
modalRef.current?.hide();
|
||||
}
|
||||
}}
|
||||
disabled={isExportDisabled}
|
||||
>
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
</ModalFooter>
|
||||
</div>
|
||||
)}
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</OverlayContainer>
|
||||
</ModalOverlay>
|
||||
);
|
||||
};
|
||||
|
@ -438,7 +438,7 @@ export const ImportExport: FC<Props> = ({ hideSettingsModal }) => {
|
||||
{isExportModalOpen && workspaceData?.activeWorkspace && (
|
||||
<ExportRequestsModal
|
||||
workspace={workspaceData.activeWorkspace}
|
||||
onHide={() => setIsExportModalOpen(false)}
|
||||
onClose={() => setIsExportModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
|
Loading…
Reference in New Issue
Block a user