Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a07404e859 | ||
|
|
b9a412279e | ||
|
|
6cceaa72b7 | ||
|
|
666cfb5944 |
@@ -12,6 +12,7 @@ export const WelcomeDialog = () => {
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="welcome-dialog"
|
||||
open={dismissed ? false : dialogOpen}
|
||||
title={
|
||||
<span className="font-alpha calt" data-testid="welcome-title">
|
||||
|
||||
@@ -82,6 +82,7 @@ export const AssetDetailsDialog = ({
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="asset-details"
|
||||
title={title}
|
||||
icon={<VegaIcon name={VegaIconNames.INFO} />}
|
||||
open={open}
|
||||
|
||||
@@ -9,7 +9,7 @@ export const NodeSwitcherDialog = ({
|
||||
setOpen: (x: boolean) => void;
|
||||
}) => {
|
||||
return (
|
||||
<Dialog open={open} onChange={setOpen} size="large">
|
||||
<Dialog open={open} onChange={setOpen} size="large" id="node-switcher">
|
||||
<NodeSwitcher closeDialog={() => setOpen(false)} />
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ export const OracleDialog = ({
|
||||
const oracleMarkets = useOracleMarkets(provider);
|
||||
return (
|
||||
<Dialog
|
||||
id="oracle-dialog"
|
||||
title={
|
||||
<OracleProfileTitle
|
||||
provider={provider}
|
||||
|
||||
@@ -55,6 +55,7 @@ export const OrderEditDialog = ({
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="order-edit-dialog"
|
||||
open={isOpen}
|
||||
onChange={onChange}
|
||||
title={t('Edit order')}
|
||||
|
||||
@@ -35,7 +35,12 @@ export const OrderViewDialog = ({
|
||||
}: OrderViewDialogProps) => {
|
||||
const [, setCopied] = useCopyTimeout();
|
||||
return (
|
||||
<Dialog open={isOpen} title={t('Order details')} onChange={onChange}>
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
title={t('Order details')}
|
||||
onChange={onChange}
|
||||
id="order-view-dialog"
|
||||
>
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow key={'order-market'}>
|
||||
<div data-testid={'order-market-label'}>{t('Market')}</div>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { useState } from 'react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { Dialog } from './dialog';
|
||||
|
||||
const QueuedDialogs = () => {
|
||||
const [open1, setOpen1] = useState(false);
|
||||
const [open2, setOpen2] = useState(false);
|
||||
const [open3, setOpen3] = useState(false);
|
||||
const onChange = (open: boolean) => void 0;
|
||||
return (
|
||||
<>
|
||||
<Dialog
|
||||
open={open1}
|
||||
dataTestId="dialog1"
|
||||
onChange={onChange}
|
||||
id="dialog1"
|
||||
>
|
||||
Dialog 1
|
||||
</Dialog>
|
||||
<Dialog
|
||||
open={open2}
|
||||
dataTestId="dialog2"
|
||||
onChange={onChange}
|
||||
id="dialog2"
|
||||
>
|
||||
Dialog 2
|
||||
</Dialog>
|
||||
<Dialog
|
||||
open={open3}
|
||||
dataTestId="dialog3"
|
||||
onChange={onChange}
|
||||
id="dialog3"
|
||||
>
|
||||
Dialog 3
|
||||
</Dialog>
|
||||
<button onClick={() => setOpen1(!open1)}>Open 1</button>
|
||||
<button onClick={() => setOpen2(!open2)}>Open 2</button>
|
||||
<button onClick={() => setOpen3(!open3)}>Open 3</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
describe('Dialog module', () => {
|
||||
it('dialogs should be queued', async () => {
|
||||
render(<QueuedDialogs />);
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Open 1'));
|
||||
expect(screen.getByTestId('dialog1')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Open 2'));
|
||||
expect(screen.queryByTestId('dialog1')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('dialog2')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Open 3'));
|
||||
expect(screen.queryByTestId('dialog2')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('dialog3')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByText('Open 3'));
|
||||
expect(screen.queryByTestId('dialog3')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('dialog2')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Open 2'));
|
||||
expect(screen.queryByTestId('dialog2')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('dialog1')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Open 1'));
|
||||
expect(screen.queryByTestId('dialog1')).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,13 +1,59 @@
|
||||
import { useEffect } from 'react';
|
||||
import React, { useEffect, useLayoutEffect } from 'react';
|
||||
import * as DialogPrimitives from '@radix-ui/react-dialog';
|
||||
import classNames from 'classnames';
|
||||
import { create } from 'zustand';
|
||||
import { subscribeWithSelector } from 'zustand/middleware';
|
||||
|
||||
import { getIntentBorder } from '../../utils/intent';
|
||||
import { VegaIcon, VegaIconNames } from '../icon';
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Intent } from '../../utils/intent';
|
||||
interface DialogProps {
|
||||
|
||||
type DialogManagerStore = {
|
||||
openOne: string;
|
||||
queueOpen: string[];
|
||||
removeFromOpen: (id: string) => void;
|
||||
setOpen: (id: string) => void;
|
||||
};
|
||||
|
||||
export const useDialogManagerStore = create<DialogManagerStore>()(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
openOne: '',
|
||||
queueOpen: [],
|
||||
removeFromOpen: (id) => {
|
||||
const queueOpen = get().queueOpen;
|
||||
let openOne = get().openOne;
|
||||
const ind = queueOpen.indexOf(id);
|
||||
if (ind > -1) {
|
||||
queueOpen.splice(ind, 1);
|
||||
}
|
||||
if (openOne === id) {
|
||||
openOne = queueOpen.shift() || '';
|
||||
}
|
||||
set({ queueOpen, openOne });
|
||||
},
|
||||
setOpen: (id: string) =>
|
||||
set((store) => {
|
||||
let openOne = store.openOne;
|
||||
const queueOpen = store.queueOpen;
|
||||
if (openOne !== id) {
|
||||
const oldOne = store.openOne;
|
||||
openOne = id;
|
||||
const ind = queueOpen.indexOf(oldOne);
|
||||
if (oldOne) {
|
||||
if (ind > -1) {
|
||||
queueOpen.splice(ind, 1);
|
||||
}
|
||||
queueOpen.unshift(oldOne);
|
||||
}
|
||||
}
|
||||
return { queueOpen, openOne };
|
||||
}),
|
||||
}))
|
||||
);
|
||||
|
||||
export interface DialogProps {
|
||||
children: ReactNode;
|
||||
open: boolean;
|
||||
onChange?: (isOpen: boolean) => void;
|
||||
@@ -18,9 +64,30 @@ interface DialogProps {
|
||||
intent?: Intent;
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
dataTestId?: string;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export function Dialog({
|
||||
export const Dialog = ({ open, id, ...props }: DialogProps) => {
|
||||
const openOne = useDialogManagerStore((store) => store.openOne);
|
||||
const queueOpen = useDialogManagerStore((store) => store.queueOpen);
|
||||
const removeFromOpen = useDialogManagerStore((store) => store.removeFromOpen);
|
||||
const setOpen = useDialogManagerStore((store) => store.setOpen);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (id) {
|
||||
if (open && openOne !== id && queueOpen.indexOf(id) === -1) {
|
||||
setOpen(id);
|
||||
} else if (!open && openOne === id && queueOpen.indexOf(id) === -1) {
|
||||
removeFromOpen(id);
|
||||
}
|
||||
}
|
||||
}, [openOne, id, open, removeFromOpen, setOpen, queueOpen]);
|
||||
|
||||
const isOpen = id ? id === openOne : open;
|
||||
return <DialogInner {...props} open={isOpen} />;
|
||||
};
|
||||
|
||||
export function DialogInner({
|
||||
children,
|
||||
open,
|
||||
onChange,
|
||||
|
||||
@@ -82,6 +82,7 @@ export const VegaConnectDialog = ({
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="connect-dialog"
|
||||
open={vegaWalletDialogOpen}
|
||||
size="small"
|
||||
onChange={onVegaWalletDialogChange}
|
||||
|
||||
@@ -23,6 +23,7 @@ export const ViewAsDialog = ({ connector }: ViewAsDialogProps) => {
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="view-as-dialog"
|
||||
open={open}
|
||||
size="small"
|
||||
onChange={(open) => {
|
||||
|
||||
@@ -21,6 +21,7 @@ export const VegaManageDialog = ({
|
||||
const { pubKey, pubKeys, selectPubKey, disconnect } = useVegaWallet();
|
||||
return (
|
||||
<Dialog
|
||||
id="wallet-manage-dialog"
|
||||
title={t('SELECT A VEGA KEY')}
|
||||
open={dialogOpen}
|
||||
onChange={setDialogOpen}
|
||||
|
||||
@@ -34,6 +34,7 @@ export const VegaTransactionDialog = ({
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id="vega-transaction-dialog"
|
||||
open={isOpen}
|
||||
onChange={onChange}
|
||||
intent={computedIntent}
|
||||
|
||||
@@ -23,6 +23,7 @@ export const EthereumTransactionDialog = ({
|
||||
const { status, error, confirmations, txHash } = transaction;
|
||||
return (
|
||||
<Dialog
|
||||
id="ethereum-transaction-dialog"
|
||||
open={transaction.dialogOpen}
|
||||
onChange={onChange}
|
||||
size="small"
|
||||
|
||||
@@ -31,6 +31,7 @@ export const Web3ConnectDialog = ({
|
||||
desiredChainId,
|
||||
}: Web3ConnectDialogProps) => (
|
||||
<Dialog
|
||||
id="web3-connect-wallet"
|
||||
open={dialogOpen}
|
||||
onChange={setDialogOpen}
|
||||
onInteractOutside={(e) => {
|
||||
|
||||
@@ -30,6 +30,7 @@ export const WithdrawalApprovalDialog = ({
|
||||
}: WithdrawalApprovalDialogProps) => {
|
||||
return (
|
||||
<Dialog
|
||||
id="withdrawal-approval-dialog"
|
||||
title={t('Save withdrawal details')}
|
||||
icon={<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />}
|
||||
open={open}
|
||||
|
||||
@@ -15,6 +15,7 @@ export const CreateWithdrawalDialog = () => {
|
||||
);
|
||||
return (
|
||||
<Dialog
|
||||
id="create-withdrawal-dialog"
|
||||
title={t('Withdraw')}
|
||||
open={isOpen && !connectWalletDialogIsOpen}
|
||||
onChange={(isOpen) => (isOpen ? open() : close())}
|
||||
|
||||
Reference in New Issue
Block a user