From 6587c57c5fa0530da8835f4376a224fcc9f90fda Mon Sep 17 00:00:00 2001 From: louis Date: Sun, 2 Feb 2025 18:32:21 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84=20Add=20Notifications=20for=20Tick?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ticker/BlueskyCard.test.tsx | 11 ++- src/components/ticker/BlueskyForm.test.tsx | 11 +-- src/components/ticker/BlueskyForm.tsx | 4 + src/components/ticker/MastodonCard.test.tsx | 5 +- src/components/ticker/MastodonForm.test.tsx | 5 +- src/components/ticker/MastodonForm.tsx | 3 + src/components/ticker/SignalGroupCard.tsx | 4 +- src/components/ticker/TelegramCard.test.tsx | 5 +- src/components/ticker/TelegramCard.tsx | 12 ++- src/components/ticker/TelegramForm.test.tsx | 5 +- src/components/ticker/TelegramForm.tsx | 3 + .../ticker/TickerListItems.test.tsx | 5 +- src/components/ticker/TickerModalDelete.tsx | 5 +- .../ticker/TickerResetModal.test.tsx | 86 +++++++++++++++++++ src/components/ticker/TickerResetModal.tsx | 5 +- .../ticker/TickerUserModalDelete.test.tsx | 71 +++++++++++++++ .../ticker/TickerUserModalDelete.tsx | 5 +- .../ticker/TickerUsersForm.test.tsx | 13 +-- src/components/ticker/TickerUsersForm.tsx | 3 + src/components/ticker/WebsiteCard.test.tsx | 5 +- src/components/ticker/WebsiteForm.test.tsx | 5 +- src/components/ticker/WebsiteForm.tsx | 3 + .../ticker/form/TickerForm.test.tsx | 5 +- src/components/ticker/form/TickerForm.tsx | 4 + 24 files changed, 248 insertions(+), 35 deletions(-) create mode 100644 src/components/ticker/TickerResetModal.test.tsx create mode 100644 src/components/ticker/TickerUserModalDelete.test.tsx diff --git a/src/components/ticker/BlueskyCard.test.tsx b/src/components/ticker/BlueskyCard.test.tsx index ac31f9e7..78f85f44 100644 --- a/src/components/ticker/BlueskyCard.test.tsx +++ b/src/components/ticker/BlueskyCard.test.tsx @@ -1,11 +1,12 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import sign from 'jwt-encode' -import BlueskyCard from './BlueskyCard' import { MemoryRouter } from 'react-router' -import { AuthProvider } from '../../contexts/AuthContext' import { Ticker } from '../../api/Ticker' -import userEvent from '@testing-library/user-event' +import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' +import BlueskyCard from './BlueskyCard' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -42,7 +43,9 @@ describe('BlueSkyCard', () => { - + + + diff --git a/src/components/ticker/BlueskyForm.test.tsx b/src/components/ticker/BlueskyForm.test.tsx index 1959d2de..3dcd52a4 100644 --- a/src/components/ticker/BlueskyForm.test.tsx +++ b/src/components/ticker/BlueskyForm.test.tsx @@ -1,11 +1,12 @@ -import sign from 'jwt-encode' -import { Ticker } from '../../api/Ticker' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' +import { Ticker } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import BlueskyForm from './BlueskyForm' -import userEvent from '@testing-library/user-event' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -44,10 +45,10 @@ describe('BlueskyForm', () => { -
+ -
+
diff --git a/src/components/ticker/BlueskyForm.tsx b/src/components/ticker/BlueskyForm.tsx index 38d1087d..59824a6b 100644 --- a/src/components/ticker/BlueskyForm.tsx +++ b/src/components/ticker/BlueskyForm.tsx @@ -5,6 +5,7 @@ import { FC } from 'react' import { useForm } from 'react-hook-form' import { Ticker, TickerBlueskyFormData, putTickerBlueskyApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' interface Props { callback: () => void @@ -12,6 +13,7 @@ interface Props { } const BlueskyForm: FC = ({ callback, ticker }) => { + const { createNotification } = useNotification() const bluesky = ticker.bluesky const { token } = useAuth() const { @@ -32,8 +34,10 @@ const BlueskyForm: FC = ({ callback, ticker }) => { putTickerBlueskyApi(token, data, ticker).then(response => { if (response.status == 'error') { setError('root.authenticationFailed', { message: 'Authentication failed' }) + createNotification({ content: 'Bluesky integration failed to update', severity: 'error' }) } else { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: 'Bluesky integration was successfully updated', severity: 'success' }) callback() } }) diff --git a/src/components/ticker/MastodonCard.test.tsx b/src/components/ticker/MastodonCard.test.tsx index b01a3233..72d6b0d2 100644 --- a/src/components/ticker/MastodonCard.test.tsx +++ b/src/components/ticker/MastodonCard.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import MastodonCard from './MastodonCard' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -42,7 +43,9 @@ describe('MastodonCard', () => { - + + + diff --git a/src/components/ticker/MastodonForm.test.tsx b/src/components/ticker/MastodonForm.test.tsx index 89fb64fc..32ee97b6 100644 --- a/src/components/ticker/MastodonForm.test.tsx +++ b/src/components/ticker/MastodonForm.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import MastodonForm from './MastodonForm' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -44,10 +45,10 @@ describe('MastodonForm', () => { -
+ -
+
diff --git a/src/components/ticker/MastodonForm.tsx b/src/components/ticker/MastodonForm.tsx index 913b2e0e..538e85f2 100644 --- a/src/components/ticker/MastodonForm.tsx +++ b/src/components/ticker/MastodonForm.tsx @@ -5,6 +5,7 @@ import { FC } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { Ticker, TickerMastodonFormData, putTickerMastodonApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' interface Props { callback: () => void @@ -12,6 +13,7 @@ interface Props { } const MastodonForm: FC = ({ callback, ticker }) => { + const { createNotification } = useNotification() const mastodon = ticker.mastodon const { token } = useAuth() const { handleSubmit, register } = useForm({ @@ -25,6 +27,7 @@ const MastodonForm: FC = ({ callback, ticker }) => { const onSubmit: SubmitHandler = data => { putTickerMastodonApi(token, data, ticker).finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: 'Mastodon integration was successfully updated', severity: 'success' }) callback() }) } diff --git a/src/components/ticker/SignalGroupCard.tsx b/src/components/ticker/SignalGroupCard.tsx index 27c3dd10..9450e297 100644 --- a/src/components/ticker/SignalGroupCard.tsx +++ b/src/components/ticker/SignalGroupCard.tsx @@ -47,7 +47,7 @@ const SignalGroupCard: FC = ({ ticker }) => { putTickerSignalGroupApi(token, { active: true }, ticker) .finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) - createNotification({ content: 'Signal group successfully configured', severity: 'success' }) + createNotification({ content: 'Signal Group enabled successfully', severity: 'success' }) setSubmittingAdd(false) }) .catch(() => { @@ -68,7 +68,7 @@ const SignalGroupCard: FC = ({ ticker }) => { deleteTickerSignalGroupApi(token, ticker) .finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) - createNotification({ content: 'Signal group deleted successfully', severity: 'success' }) + createNotification({ content: 'Signal Group deleted successfully', severity: 'success' }) }) .catch(() => { createNotification({ content: 'Failed to delete Signal group', severity: 'error' }) diff --git a/src/components/ticker/TelegramCard.test.tsx b/src/components/ticker/TelegramCard.test.tsx index e1fcb43e..45f64435 100644 --- a/src/components/ticker/TelegramCard.test.tsx +++ b/src/components/ticker/TelegramCard.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import TelegramCard from './TelegramCard' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -42,7 +43,9 @@ describe('TelegramCard', () => { - + + + diff --git a/src/components/ticker/TelegramCard.tsx b/src/components/ticker/TelegramCard.tsx index a841731c..91d1751c 100644 --- a/src/components/ticker/TelegramCard.tsx +++ b/src/components/ticker/TelegramCard.tsx @@ -6,6 +6,7 @@ import { useQueryClient } from '@tanstack/react-query' import { FC, useCallback, useState } from 'react' import { Ticker, deleteTickerTelegramApi, putTickerTelegramApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' import TelegramModalForm from './TelegramModalForm' interface Props { @@ -13,6 +14,7 @@ interface Props { } const TelegramCard: FC = ({ ticker }) => { + const { createNotification } = useNotification() const { token } = useAuth() const [open, setOpen] = useState(false) const queryClient = useQueryClient() @@ -20,14 +22,18 @@ const TelegramCard: FC = ({ ticker }) => { const telegram = ticker.telegram const handleToggle = useCallback(() => { - putTickerTelegramApi(token, { active: !telegram.active }, ticker).finally(() => queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] })) - }, [token, queryClient, telegram.active, ticker]) + putTickerTelegramApi(token, { active: !telegram.active }, ticker).finally(() => { + queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: `Telegram integration ${telegram.active ? 'disabled' : 'enabled'} successfully`, severity: 'success' }) + }) + }, [token, telegram.active, ticker, queryClient, createNotification]) const handleDelete = useCallback(() => { deleteTickerTelegramApi(token, ticker).finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: 'Telegram integration successfully deleted', severity: 'success' }) }) - }, [token, queryClient, ticker]) + }, [token, ticker, queryClient, createNotification]) const channelLink = ( diff --git a/src/components/ticker/TelegramForm.test.tsx b/src/components/ticker/TelegramForm.test.tsx index c1da522d..72b84c38 100644 --- a/src/components/ticker/TelegramForm.test.tsx +++ b/src/components/ticker/TelegramForm.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import TelegramForm from './TelegramForm' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -44,10 +45,10 @@ describe('TelegramForm', () => { -
+ -
+
diff --git a/src/components/ticker/TelegramForm.tsx b/src/components/ticker/TelegramForm.tsx index a7790d12..3e34e57b 100644 --- a/src/components/ticker/TelegramForm.tsx +++ b/src/components/ticker/TelegramForm.tsx @@ -5,6 +5,7 @@ import { FC } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { Ticker, putTickerTelegramApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' interface Props { callback: () => void @@ -17,6 +18,7 @@ interface FormValues { } const TelegramForm: FC = ({ callback, ticker }) => { + const { createNotification } = useNotification() const telegram = ticker.telegram const { token } = useAuth() const { handleSubmit, register } = useForm({ @@ -30,6 +32,7 @@ const TelegramForm: FC = ({ callback, ticker }) => { const onSubmit: SubmitHandler = data => { putTickerTelegramApi(token, data, ticker).finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: 'Telegram integration was successfully updated', severity: 'success' }) callback() }) } diff --git a/src/components/ticker/TickerListItems.test.tsx b/src/components/ticker/TickerListItems.test.tsx index b933928e..05221a83 100644 --- a/src/components/ticker/TickerListItems.test.tsx +++ b/src/components/ticker/TickerListItems.test.tsx @@ -4,6 +4,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { GetTickersQueryParams } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import TickerListItems from './TickerListItems' describe('TickerListItems', function () { @@ -35,7 +36,9 @@ describe('TickerListItems', function () { - + + + diff --git a/src/components/ticker/TickerModalDelete.tsx b/src/components/ticker/TickerModalDelete.tsx index 39a47616..3f4fc178 100644 --- a/src/components/ticker/TickerModalDelete.tsx +++ b/src/components/ticker/TickerModalDelete.tsx @@ -2,6 +2,7 @@ import { useQueryClient } from '@tanstack/react-query' import { FC, useCallback } from 'react' import { Ticker, deleteTickerApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' import Modal from '../common/Modal' interface Props { @@ -11,14 +12,16 @@ interface Props { } const TickerModalDelete: FC = ({ open, onClose, ticker }) => { + const { createNotification } = useNotification() const { token } = useAuth() const queryClient = useQueryClient() const handleDelete = useCallback(() => { deleteTickerApi(token, ticker).finally(() => { queryClient.invalidateQueries({ queryKey: ['tickers'] }) + createNotification({ content: 'Ticker was successfully deleted', severity: 'success' }) }) - }, [token, ticker, queryClient]) + }, [token, ticker, queryClient, createNotification]) return ( diff --git a/src/components/ticker/TickerResetModal.test.tsx b/src/components/ticker/TickerResetModal.test.tsx new file mode 100644 index 00000000..61cef300 --- /dev/null +++ b/src/components/ticker/TickerResetModal.test.tsx @@ -0,0 +1,86 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import sign from 'jwt-encode' +import { MemoryRouter } from 'react-router' +import { Ticker } from '../../api/Ticker' +import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' +import TickerResetModal from './TickerResetModal' + +const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') + +describe('TickerResetModal', () => { + beforeAll(() => { + localStorage.setItem('token', token) + }) + + beforeEach(() => { + fetchMock.resetMocks() + onClose.mockClear() + }) + + const onClose = vi.fn() + + function setup(ticker: Ticker) { + const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }) + return render( + + + + + + + + + + ) + } + + it('should render the component', async () => { + const ticker = { + id: 1, + title: 'Ticker 1', + } as Ticker + setup(ticker) + + expect(screen.getByRole('button', { name: 'Reset' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Close' })).toBeInTheDocument() + + fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' })) + + await userEvent.click(screen.getByRole('button', { name: 'Reset' })) + + expect(onClose).toHaveBeenCalledTimes(1) + expect(fetchMock).toHaveBeenCalledTimes(1) + expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/v1/admin/tickers/1/reset', { + method: 'put', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }) + }) + + it('should render the component and close the modal', async () => { + const ticker = { + id: 1, + title: 'Ticker 1', + } as Ticker + setup(ticker) + + fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' })) + + await userEvent.click(screen.getByRole('button', { name: 'Close' })) + + expect(onClose).toHaveBeenCalledTimes(1) + expect(fetchMock).toHaveBeenCalledTimes(0) + }) +}) diff --git a/src/components/ticker/TickerResetModal.tsx b/src/components/ticker/TickerResetModal.tsx index b86b835d..913a42e7 100644 --- a/src/components/ticker/TickerResetModal.tsx +++ b/src/components/ticker/TickerResetModal.tsx @@ -2,6 +2,7 @@ import { useQueryClient } from '@tanstack/react-query' import { FC, useCallback } from 'react' import { Ticker, putTickerResetApi } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' import Modal from '../common/Modal' interface Props { @@ -11,6 +12,7 @@ interface Props { } const TickerResetModal: FC = ({ onClose, open, ticker }) => { + const { createNotification } = useNotification() const { token } = useAuth() const queryClient = useQueryClient() @@ -22,9 +24,10 @@ const TickerResetModal: FC = ({ onClose, open, ticker }) => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) }) .finally(() => { + createNotification({ content: 'Ticker has been successfully reset', severity: 'success' }) onClose() }) - }, [onClose, token, queryClient, ticker]) + }, [token, ticker, queryClient, createNotification, onClose]) return ( diff --git a/src/components/ticker/TickerUserModalDelete.test.tsx b/src/components/ticker/TickerUserModalDelete.test.tsx new file mode 100644 index 00000000..f3bc816f --- /dev/null +++ b/src/components/ticker/TickerUserModalDelete.test.tsx @@ -0,0 +1,71 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import sign from 'jwt-encode' +import { MemoryRouter } from 'react-router' +import { Ticker } from '../../api/Ticker' +import { User } from '../../api/User' +import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' +import TickerUserModalDelete from './TickerUserModalDelete' + +const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') + +describe('TickerUserModalDelete', () => { + beforeAll(() => { + localStorage.setItem('token', token) + }) + + beforeEach(() => { + fetchMock.resetMocks() + }) + + function setup(ticker: Ticker, user: User, open: boolean) { + const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }) + return render( + + + + + + + + + + ) + } + + it('should render the component', async () => { + const ticker = { + id: 1, + title: 'Ticker 1', + } as Ticker + const user = { + id: 1, + email: 'user@example.org', + } as User + setup(ticker, user, true) + + expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument() + + fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' })) + + await userEvent.click(screen.getByRole('button', { name: 'Delete' })) + + expect(fetchMock).toHaveBeenCalledTimes(1) + expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/v1/admin/tickers/1/users/1', { + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + method: 'delete', + }) + }) +}) diff --git a/src/components/ticker/TickerUserModalDelete.tsx b/src/components/ticker/TickerUserModalDelete.tsx index 932ffd20..a60ce863 100644 --- a/src/components/ticker/TickerUserModalDelete.tsx +++ b/src/components/ticker/TickerUserModalDelete.tsx @@ -3,6 +3,7 @@ import { FC, useCallback } from 'react' import { Ticker, deleteTickerUserApi } from '../../api/Ticker' import { User } from '../../api/User' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' import Modal from '../common/Modal' interface Props { @@ -13,15 +14,17 @@ interface Props { } const TickerUserModalDelete: FC = ({ open, onClose, ticker, user }) => { + const { createNotification } = useNotification() const { token } = useAuth() const queryClient = useQueryClient() const handleDelete = useCallback(() => { deleteTickerUserApi(token, ticker, user).finally(() => { queryClient.invalidateQueries({ queryKey: ['tickerUsers', ticker.id] }) + createNotification({ content: 'User is successfully deleted from ticker', severity: 'success' }) onClose() }) - }, [token, ticker, user, queryClient, onClose]) + }, [token, ticker, user, queryClient, createNotification, onClose]) return ( diff --git a/src/components/ticker/TickerUsersForm.test.tsx b/src/components/ticker/TickerUsersForm.test.tsx index 547c1cce..ba8797c7 100644 --- a/src/components/ticker/TickerUsersForm.test.tsx +++ b/src/components/ticker/TickerUsersForm.test.tsx @@ -1,12 +1,13 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { Ticker } from '../../api/Ticker' -import { User } from '../../api/User' import { render, screen } from '@testing-library/react' -import TickerUsersForm from './TickerUsersForm' -import { vi } from 'vitest' import userEvent from '@testing-library/user-event' import { MemoryRouter } from 'react-router' +import { vi } from 'vitest' +import { Ticker } from '../../api/Ticker' +import { User } from '../../api/User' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' +import TickerUsersForm from './TickerUsersForm' describe('TickerUsersForm', () => { beforeEach(() => { @@ -25,7 +26,9 @@ describe('TickerUsersForm', () => { - + + + diff --git a/src/components/ticker/TickerUsersForm.tsx b/src/components/ticker/TickerUsersForm.tsx index 75b98139..97626cc9 100644 --- a/src/components/ticker/TickerUsersForm.tsx +++ b/src/components/ticker/TickerUsersForm.tsx @@ -5,6 +5,7 @@ import { SubmitHandler, useForm } from 'react-hook-form' import { Ticker, putTickerUsersApi } from '../../api/Ticker' import { User, fetchUsersApi } from '../../api/User' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' interface Props { ticker: Ticker @@ -17,6 +18,7 @@ interface FormValues { } const TickerUsersForm: FC = ({ onSubmit, ticker, defaultValue }) => { + const { createNotification } = useNotification() const [users, setUsers] = useState>(defaultValue) const [options, setOptions] = useState>([]) const { token } = useAuth() @@ -35,6 +37,7 @@ const TickerUsersForm: FC = ({ onSubmit, ticker, defaultValue }) => { const updateTickerUsers: SubmitHandler = () => { putTickerUsersApi(token, ticker, users).then(() => { queryClient.invalidateQueries({ queryKey: ['tickerUsers', ticker.id] }) + createNotification({ content: 'Users were successfully updated', severity: 'success' }) onSubmit() }) } diff --git a/src/components/ticker/WebsiteCard.test.tsx b/src/components/ticker/WebsiteCard.test.tsx index 151c55a6..2c3890f6 100644 --- a/src/components/ticker/WebsiteCard.test.tsx +++ b/src/components/ticker/WebsiteCard.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker, TickerWebsite } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import WebsiteCard from './WebsiteCard' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -37,10 +38,10 @@ describe('WebsiteCard', () => { -
+ -
+
diff --git a/src/components/ticker/WebsiteForm.test.tsx b/src/components/ticker/WebsiteForm.test.tsx index 20c570f5..c862a49f 100644 --- a/src/components/ticker/WebsiteForm.test.tsx +++ b/src/components/ticker/WebsiteForm.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker, TickerWebsite } from '../../api/Ticker' import { AuthProvider } from '../../contexts/AuthContext' +import { NotificationProvider } from '../../contexts/NotificationContext' import WebsiteForm from './WebsiteForm' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -39,10 +40,10 @@ describe('WebsiteForm', () => { -
+ -
+
diff --git a/src/components/ticker/WebsiteForm.tsx b/src/components/ticker/WebsiteForm.tsx index 8519b1d2..6ab4a6a9 100644 --- a/src/components/ticker/WebsiteForm.tsx +++ b/src/components/ticker/WebsiteForm.tsx @@ -6,6 +6,7 @@ import { FC } from 'react' import { SubmitHandler, useFieldArray, useForm } from 'react-hook-form' import { putTickerWebsitesApi, Ticker, TickerWebsite } from '../../api/Ticker' import useAuth from '../../contexts/useAuth' +import useNotification from '../../contexts/useNotification' interface Props { callback: () => void @@ -18,6 +19,7 @@ interface FormData { const WebsiteForm: FC = ({ callback, ticker }) => { const websites = ticker.websites + const { createNotification } = useNotification() const { token } = useAuth() const { control, @@ -37,6 +39,7 @@ const WebsiteForm: FC = ({ callback, ticker }) => { const onSubmit: SubmitHandler = data => { putTickerWebsitesApi(token, ticker, data.websites).finally(() => { queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) + createNotification({ content: 'Websites were successfully updated', severity: 'success' }) callback() }) } diff --git a/src/components/ticker/form/TickerForm.test.tsx b/src/components/ticker/form/TickerForm.test.tsx index a59b67a4..ff3f44cc 100644 --- a/src/components/ticker/form/TickerForm.test.tsx +++ b/src/components/ticker/form/TickerForm.test.tsx @@ -5,6 +5,7 @@ import sign from 'jwt-encode' import { MemoryRouter } from 'react-router' import { Ticker } from '../../../api/Ticker' import { AuthProvider } from '../../../contexts/AuthContext' +import { NotificationProvider } from '../../../contexts/NotificationContext' import TickerForm from './TickerForm' const token = sign({ id: 1, email: 'user@example.org', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') @@ -35,10 +36,10 @@ describe('TickerForm', () => { -
+ -
+
diff --git a/src/components/ticker/form/TickerForm.tsx b/src/components/ticker/form/TickerForm.tsx index 04e349b0..f6263b9b 100644 --- a/src/components/ticker/form/TickerForm.tsx +++ b/src/components/ticker/form/TickerForm.tsx @@ -6,6 +6,7 @@ import { FormProvider, SubmitHandler, useForm } from 'react-hook-form' import { MapContainer, Marker, TileLayer } from 'react-leaflet' import { postTickerApi, putTickerApi, Ticker, TickerFormData } from '../../../api/Ticker' import useAuth from '../../../contexts/useAuth' +import useNotification from '../../../contexts/useNotification' import LocationSearch, { Result } from '../LocationSearch' import Active from './Active' import Author from './Author' @@ -29,6 +30,7 @@ interface Props { } const TickerForm: FC = ({ callback, id, ticker, setSubmitting }) => { + const { createNotification } = useNotification() const form = useForm({ defaultValues: { title: ticker?.title, @@ -81,12 +83,14 @@ const TickerForm: FC = ({ callback, id, ticker, setSubmitting }) => { queryClient.invalidateQueries({ queryKey: ['tickers'] }) queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] }) setSubmitting(false) + createNotification({ content: 'Ticker was successfully updated', severity: 'success' }) callback() }) } else { postTickerApi(token, data).finally(() => { queryClient.invalidateQueries({ queryKey: ['tickers'] }) setSubmitting(false) + createNotification({ content: 'Ticker was successfully created', severity: 'success' }) callback() }) }