mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-05-27 07:36:34 +00:00
Migrate DeleteServerModal to tailwind components
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import type { ExitAction } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||||
import { CardModal } from '@shlinkio/shlink-frontend-kit/tailwind';
|
import { CardModal } from '@shlinkio/shlink-frontend-kit/tailwind';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
@@ -14,10 +15,11 @@ type DeleteServerModalConnectProps = DeleteServerModalProps & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ({ server, onClose, open, deleteServer }) => {
|
export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ({ server, onClose, open, deleteServer }) => {
|
||||||
const onConfirm = useCallback(() => {
|
const onClosed = useCallback((exitAction: ExitAction) => {
|
||||||
deleteServer(server);
|
if (exitAction === 'confirm') {
|
||||||
onClose(true);
|
deleteServer(server);
|
||||||
}, [deleteServer, onClose, server]);
|
}
|
||||||
|
}, [deleteServer, server]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardModal
|
<CardModal
|
||||||
@@ -25,16 +27,19 @@ export const DeleteServerModal: FC<DeleteServerModalConnectProps> = ({ server, o
|
|||||||
title="Remove server"
|
title="Remove server"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
onClose={() => onClose(false)}
|
onClose={() => onClose(false)}
|
||||||
onConfirm={onConfirm}
|
onConfirm={() => onClose(true)}
|
||||||
|
onClosed={onClosed}
|
||||||
confirmText="Delete"
|
confirmText="Delete"
|
||||||
>
|
>
|
||||||
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
|
<div className="tw:flex tw:flex-col tw:gap-y-4">
|
||||||
<p>
|
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
|
||||||
<i>
|
<p>
|
||||||
No data will be deleted, only the access to this server will be removed from this device.
|
<i>
|
||||||
You can create it again at any moment.
|
No data will be deleted, only the access to this server will be removed from this device.
|
||||||
</i>
|
You can create it again at any moment.
|
||||||
</p>
|
</i>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</CardModal>
|
</CardModal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,8 +47,9 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
|
|||||||
|
|
||||||
const create = useCallback((serversData: ServerWithId[]) => {
|
const create = useCallback((serversData: ServerWithId[]) => {
|
||||||
createServers(serversData);
|
createServers(serversData);
|
||||||
|
hideModal();
|
||||||
onImport();
|
onImport();
|
||||||
}, [createServers, onImport]);
|
}, [createServers, hideModal, onImport]);
|
||||||
const onFile = useCallback(
|
const onFile = useCallback(
|
||||||
async ({ target }: ChangeEvent<HTMLInputElement>) =>
|
async ({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||||
serversImporter.importServersFromFile(target.files?.[0])
|
serversImporter.importServersFromFile(target.files?.[0])
|
||||||
@@ -73,14 +74,8 @@ const ImportServersBtn: FCWithDeps<ImportServersBtnConnectProps, ImportServersBt
|
|||||||
[create, onImportError, servers, serversImporter, showModal],
|
[create, onImportError, servers, serversImporter, showModal],
|
||||||
);
|
);
|
||||||
|
|
||||||
const createAllServers = useCallback(() => {
|
const createAllServers = useCallback(() => create(importedServersRef.current), [create]);
|
||||||
create(importedServersRef.current);
|
const createNonDuplicatedServers = useCallback(() => create(newServersRef.current), [create]);
|
||||||
hideModal();
|
|
||||||
}, [create, hideModal]);
|
|
||||||
const createNonDuplicatedServers = useCallback(() => {
|
|
||||||
create(newServersRef.current);
|
|
||||||
hideModal();
|
|
||||||
}, [create, hideModal]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { FC, ReactElement } from 'react';
|
import type { FC, ReactElement } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useEffect , useState } from 'react';
|
||||||
|
|
||||||
export type RenderModalArgs = {
|
export type RenderModalArgs = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -12,5 +12,13 @@ export const TestModalWrapper: FC<{ renderModal: (args: RenderModalArgs) => Reac
|
|||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const onClose = useCallback(() => setOpen(false), []);
|
const onClose = useCallback(() => setOpen(false), []);
|
||||||
|
|
||||||
|
// Workaround to ensure CardModals from shlink-frontend-shared can be closed, as they depend on CSS transitions
|
||||||
|
// Since JSDOM does not support them, this dispatches the event right after the listener has been set-up
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
document.querySelector('[data-testid="transition-container"]')?.dispatchEvent(new Event('transitionend'));
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
return renderModal({ open, onClose });
|
return renderModal({ open, onClose });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
||||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||||
@@ -36,13 +36,15 @@ describe('<DeleteServerModal />', () => {
|
|||||||
expect(screen.getByText(serverName)).toBeInTheDocument();
|
expect(screen.getByText(serverName)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.only.each([
|
||||||
[() => screen.getByRole('button', { name: 'Cancel' })],
|
[() => screen.getByRole('button', { name: 'Cancel' })],
|
||||||
[() => screen.getByLabelText('Close dialog')],
|
[() => screen.getByLabelText('Close dialog')],
|
||||||
])('toggles when clicking cancel button', async (getButton) => {
|
])('closes dialog when clicking cancel button', async (getButton) => {
|
||||||
const { user } = setUp();
|
const { user } = setUp();
|
||||||
|
|
||||||
|
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
||||||
await user.click(getButton());
|
await user.click(getButton());
|
||||||
|
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||||
expect(deleteServerMock).not.toHaveBeenCalled();
|
expect(deleteServerMock).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +53,6 @@ describe('<DeleteServerModal />', () => {
|
|||||||
|
|
||||||
expect(deleteServerMock).not.toHaveBeenCalled();
|
expect(deleteServerMock).not.toHaveBeenCalled();
|
||||||
await user.click(screen.getByRole('button', { name: 'Delete' }));
|
await user.click(screen.getByRole('button', { name: 'Delete' }));
|
||||||
|
expect(deleteServerMock).toHaveBeenCalledOnce();
|
||||||
await waitFor(() => expect(deleteServerMock).toHaveBeenCalledTimes(1));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Silent warnings triggered by reactstrap components, as it's getting removed
|
||||||
|
onConsoleLog: (log) => !log.includes('`transition.timeout` is marked as required'),
|
||||||
|
|
||||||
// Workaround for bug in react-router (or vitest module resolution) which causes different react-router versions to
|
// Workaround for bug in react-router (or vitest module resolution) which causes different react-router versions to
|
||||||
// be resolved for the main package and dependencies who have a peer dependency in react-router.
|
// be resolved for the main package and dependencies who have a peer dependency in react-router.
|
||||||
// This ensures always the same version is resolved.
|
// This ensures always the same version is resolved.
|
||||||
|
|||||||
Reference in New Issue
Block a user