diff --git a/src/servers/CreateServer.tsx b/src/servers/CreateServer.tsx index b0e65f09..6eb3c2da 100644 --- a/src/servers/CreateServer.tsx +++ b/src/servers/CreateServer.tsx @@ -1,13 +1,14 @@ -import { FC } from 'react'; +import { FC, useEffect, useState } from 'react'; import { v4 as uuid } from 'uuid'; import { RouterProps } from 'react-router'; import { Button } from 'reactstrap'; import { Result } from '../utils/Result'; import { NoMenuLayout } from '../common/NoMenuLayout'; -import { StateFlagTimeout } from '../utils/helpers/hooks'; +import { StateFlagTimeout, useToggle } from '../utils/helpers/hooks'; import { ServerForm } from './helpers/ServerForm'; import { ImportServersBtnProps } from './helpers/ImportServersBtn'; import { ServerData, ServersMap, ServerWithId } from './data'; +import { DuplicatedServerModal } from './helpers/DuplicatedServerModal'; const SHOW_IMPORT_MSG_TIME = 4000; @@ -31,16 +32,30 @@ const CreateServer = (ImportServersBtn: FC, useStateFlagT const hasServers = !!Object.keys(servers).length; const [ serversImported, setServersImported ] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME); const [ errorImporting, setErrorImporting ] = useStateFlagTimeout(false, SHOW_IMPORT_MSG_TIME); - const handleSubmit = (serverData: ServerData) => { + const [ isConfirmModalOpen, toggleConfirmModal ] = useToggle(); + const [ serverData, setServerData ] = useState(); + const save = () => { + if (!serverData) { + return; + } + const id = uuid(); createServer({ ...serverData, id }); push(`/server/${id}`); }; + useEffect(() => { + const serverExists = Object.values(servers).some( + ({ url, apiKey }) => serverData?.url === url && serverData?.apiKey === apiKey, + ); + + serverExists ? toggleConfirmModal() : save(); + }, [ serverData ]); + return ( - Add new server} onSubmit={handleSubmit}> + Add new server} onSubmit={setServerData}> {!hasServers && } {hasServers && } @@ -49,6 +64,14 @@ const CreateServer = (ImportServersBtn: FC, useStateFlagT {serversImported && } {errorImporting && } + + ); }; diff --git a/src/servers/helpers/DuplicatedServerModal.tsx b/src/servers/helpers/DuplicatedServerModal.tsx new file mode 100644 index 00000000..497174c2 --- /dev/null +++ b/src/servers/helpers/DuplicatedServerModal.tsx @@ -0,0 +1,31 @@ +import { FC } from 'react'; +import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ServerData } from '../data'; + +interface DuplicatedServerModalProps { + serverData?: ServerData; + isOpen: boolean; + toggle: () => void; + onDiscard: () => void; + onSave: () => void; +} + +export const DuplicatedServerModal: FC = ( + { isOpen, toggle, serverData, onDiscard, onSave }, +) => ( + + Duplicated server + +

There is already a server with:

+
    +
  • URL: {serverData?.url}
  • +
  • API key: {serverData?.apiKey}
  • +
+ Do you want to save this server anyway? +
+ + + + +
+); diff --git a/test/servers/CreateServer.test.tsx b/test/servers/CreateServer.test.tsx index 7cb2e388..795db3e4 100644 --- a/test/servers/CreateServer.test.tsx +++ b/test/servers/CreateServer.test.tsx @@ -4,18 +4,21 @@ import { History } from 'history'; import createServerConstruct from '../../src/servers/CreateServer'; import { ServerForm } from '../../src/servers/helpers/ServerForm'; import { ServerWithId } from '../../src/servers/data'; +import { DuplicatedServerModal } from '../../src/servers/helpers/DuplicatedServerModal'; describe('', () => { let wrapper: ShallowWrapper; const ImportServersBtn = () => null; const createServerMock = jest.fn(); const push = jest.fn(); - const historyMock = Mock.of({ push }); + const goBack = jest.fn(); + const historyMock = Mock.of({ push, goBack }); const servers = { foo: Mock.all() }; const createWrapper = (serversImported = false, importFailed = false) => { const useStateFlagTimeout = jest.fn() .mockReturnValueOnce([ serversImported, () => '' ]) - .mockReturnValueOnce([ importFailed, () => '' ]); + .mockReturnValueOnce([ importFailed, () => '' ]) + .mockReturnValue([]); const CreateServer = createServerConstruct(ImportServersBtn, useStateFlagTimeout); wrapper = shallow(); @@ -23,10 +26,8 @@ describe('', () => { return wrapper; }; - afterEach(() => { - jest.resetAllMocks(); - wrapper?.unmount(); - }); + beforeEach(jest.clearAllMocks); + afterEach(() => wrapper?.unmount()); it('renders components', () => { const wrapper = createWrapper(); @@ -51,13 +52,30 @@ describe('', () => { expect(result.prop('type')).toEqual('error'); }); - it('creates server and redirects to it when form is submitted', () => { + it('creates server data form is submitted', () => { const wrapper = createWrapper(); const form = wrapper.find(ServerForm); + expect(wrapper.find(DuplicatedServerModal).prop('serverData')).not.toBeDefined(); form.simulate('submit', {}); + expect(wrapper.find(DuplicatedServerModal).prop('serverData')).toEqual({}); + }); + + it('saves server and redirects on modal save', () => { + const wrapper = createWrapper(); + + wrapper.find(ServerForm).simulate('submit', {}); + wrapper.find(DuplicatedServerModal).simulate('save'); expect(createServerMock).toHaveBeenCalledTimes(1); expect(push).toHaveBeenCalledTimes(1); }); + + it('goes back on modal discard', () => { + const wrapper = createWrapper(); + + wrapper.find(DuplicatedServerModal).simulate('discard'); + + expect(goBack).toHaveBeenCalledTimes(1); + }); });