diff --git a/public/locales/en.json b/public/locales/en.json index 668c0fae94..de4787b7b2 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -47,7 +47,7 @@ "leftDrawer": { "talawaAdminPortal": "Talawa Admin Portal", "menu": "Menu", - "organizations": "Organizations", + "my organizations": "My Organizations", "requests": "Requests", "users": "Users", "logout": "Logout" @@ -84,7 +84,7 @@ "designation": "Designation", "email": "Email", "searchByName": "Search By Name", - "organizations": "Organizations", + "my organizations": "My Organizations", "createOrganization": "Create Organization", "createSampleOrganization": "Create Sample Organization", "description": "Description", @@ -682,7 +682,11 @@ "deleteAdvertisement": "Delete Advertisement", "deleteAdvertisementMsg": "Do you want to remove this advertisement?", "no": "No", - "yes": "Yes" + "yes": "Yes", + "view": "View", + "edit": "Edit", + "editAdvertisement": "Edit Advertisement", + "saveChanges": "Save Changes" }, "userChat": { "chat": "Chat", diff --git a/public/locales/fr.json b/public/locales/fr.json index 16c4206a4d..dacb926a6f 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -42,7 +42,7 @@ "leftDrawer": { "talawaAdminPortal": "Portail d'administration Talawa", "menu": "Menu", - "organizations": "Organisations", + "my organizations": "Mes Organisations", "requests": "Demandes", "users": "Utilisateurs", "logout": "Déconnexion" @@ -78,7 +78,7 @@ "designation": "La désignation", "email": "E-mail", "searchByName": "Rechercher par nom", - "organizations": "Organisations", + "my organizations": "Mes Organisations", "createOrganization": "Créer une organisation", "createSampleOrganization": "Créer une organisation d'exemple", "description": "La description", @@ -662,7 +662,11 @@ "deleteAdvertisement": "Supprimer l'annonce", "deleteAdvertisementMsg": "Voulez-vous supprimer cette annonce ?", "no": "Non", - "yes": "Oui" + "yes": "Oui", + "view": "Voir", + "edit": "Éditer", + "editAdvertisement": "Éditer l'annonce", + "saveChanges": "Enregistrer les modifications" }, "userChat": { "chat": "Chat", diff --git a/public/locales/hi.json b/public/locales/hi.json index e917f3b49d..f470e327a8 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -42,7 +42,7 @@ "leftDrawer": { "talawaAdminPortal": "तलावा व्यवस्थापक पोर्टल", "menu": "मेन्यू", - "organizations": "संगठन", + "my organizations": "मेरे संगठन", "requests": "अनुरोध", "users": "उपयोगकर्ता", "logout": "लॉग आउट" @@ -78,7 +78,7 @@ "designation": "पद", "email": "ईमेल", "searchByName": "नाम से खोजें", - "organizations": "संगठन", + "my organizations": "मेरे संगठन", "createOrganization": "संगठन बनाएं", "createSampleOrganization": " सैंपल संगठन बनाएं", "description": "विवरण", @@ -662,7 +662,11 @@ "deleteAdvertisement": "विज्ञापन हटाएं", "deleteAdvertisementMsg": "क्या आप इस विज्ञापन को हटाना चाहते हैं?", "no": "नहीं", - "yes": "हाँ" + "yes": "हाँ", + "view": "देखें", + "edit": "संपादित करें", + "editAdvertisement": "विज्ञापन संपादित करें", + "saveChanges": "परिवर्तन सहेजें" }, "userChat": { "chat": "बात", diff --git a/public/locales/sp.json b/public/locales/sp.json index f90fcad222..c273777949 100644 --- a/public/locales/sp.json +++ b/public/locales/sp.json @@ -42,7 +42,7 @@ "leftDrawer": { "talawaAdminPortal": "Portal de administración de Talawa", "menu": "Menú", - "organizations": "Organizaciones", + "my organizations": "Mis Organizaciones", "requests": "Solicitudes", "users": "Usuarios", "logout": "Cerrar sesión" @@ -78,7 +78,7 @@ "designation": "Designacion", "email": "Correo electrónico", "searchByName": "Buscar por nombre", - "organizations": "Organizaciones", + "my organizations": "Mis Organizaciones.", "createOrganization": "Crear organización", "createSampleOrganization": "Crear organización de muestra", "description": "Descripción", @@ -662,7 +662,11 @@ "deleteAdvertisement": "Eliminar anuncio", "deleteAdvertisementMsg": "¿Desea eliminar este anuncio?", "no": "No", - "yes": "Sí" + "yes": "Sí", + "view": "Ver", + "edit": "Editar", + "editAdvertisement": "Editar Anuncio", + "saveChanges": "Guardar Cambios" }, "userChat": { "chat": "Charlar", diff --git a/public/locales/zh.json b/public/locales/zh.json index 4f439fb086..b03c3ac8e2 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -42,7 +42,7 @@ "leftDrawer": { "talawaAdminPortal": "塔拉瓦管理门户", "menu": "菜单", - "organizations": "组织", + "my organizations": "我的组织", "requests": "请求", "users": "用户", "logout": "退出登录" @@ -78,7 +78,7 @@ "designation": "指定", "email": "電子郵件", "searchByName": "按名稱搜索", - "organizations": "组织", + "my organizations": "我的组织", "createOrganization": "創建組織", "createSampleOrganization": "创建示范组织", "description": "描述", @@ -662,7 +662,11 @@ "deleteAdvertisement": "删除广告", "deleteAdvertisementMsg": "您是否要删除此广告?", "no": "不", - "yes": "是" + "yes": "是", + "view": "查看", + "edit": "编辑", + "editAdvertisement": "编辑广告", + "saveChanges": "保存更改" }, "userChat": { "chat": "聊天", diff --git a/src/GraphQl/Mutations/mutations.ts b/src/GraphQl/Mutations/mutations.ts index f25abab4ef..a1a755eeaf 100644 --- a/src/GraphQl/Mutations/mutations.ts +++ b/src/GraphQl/Mutations/mutations.ts @@ -440,6 +440,29 @@ export const ADD_ADVERTISEMENT_MUTATION = gql` } } `; +export const UPDATE_ADVERTISEMENT_MUTATION = gql` + mutation UpdateAdvertisement( + $id: ID! + $name: String + $link: String + $type: String + $startDate: Date + $endDate: Date + ) { + updateAdvertisement( + id: $id + data: { + name: $name + link: $link + type: $type + startDate: $startDate + endDate: $endDate + } + ) { + _id + } + } +`; export const DELETE_ADVERTISEMENT_BY_ID = gql` mutation ($id: ID!) { deleteAdvertisementById(id: $id) { diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.test.tsx index bec43589b6..6113609ebe 100644 --- a/src/components/Advertisements/Advertisements.test.tsx +++ b/src/components/Advertisements/Advertisements.test.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import 'jest-location-mock'; +import { act, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import { ApolloClient, @@ -17,7 +18,14 @@ import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; -import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; +import { + ADVERTISEMENTS_GET, + ORGANIZATIONS_LIST, + PLUGIN_GET, +} from 'GraphQl/Queries/Queries'; +import userEvent from '@testing-library/user-event'; +import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { ToastContainer } from 'react-toastify'; const httpLink = new HttpLink({ uri: BACKEND_URL, @@ -26,49 +34,336 @@ const httpLink = new HttpLink({ }, }); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + const client: ApolloClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([httpLink]), }); -describe('Testing Advertisement Component', () => { - test('Temporary test for Advertisement', () => { - expect(true).toBe(true); - const { getByTestId } = render( + +jest.mock('components/AddOn/support/services/Plugin.helper', () => ({ + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + fetchInstalled: jest.fn().mockResolvedValue([]), + fetchStore: jest.fn().mockResolvedValue([]), + })), +})); + +const today = new Date(); +const tomorrow = today; +tomorrow.setDate(today.getDate() + 1); + +const PLUGIN_GET_MOCK = { + request: { + query: PLUGIN_GET, + }, + result: { + data: { + getPlugins: [ + { + _id: '6581be50e88e74003aab436c', + pluginName: 'Chats', + pluginCreatedBy: 'Talawa Team', + pluginDesc: + 'User can share messages with other users in a chat user interface.', + uninstalledOrgs: [ + '62ccfccd3eb7fd2a30f41601', + '62ccfccd3eb7fd2a30f41601', + ], + __typename: 'Plugin', + }, + ], + }, + loading: false, + }, +}; + +const ADD_ADVERTISEMENT_MUTATION_MOCK = { + request: { + query: ADD_ADVERTISEMENT_MUTATION, + variables: { + orgId: 'undefined', + name: 'Cookie Shop', + link: 'http://yourwebsite.com/photo', + type: 'POPUP', + startDate: '2023-01-01', + endDate: '2023-02-02', + }, + }, + result: { + data: { + createAdvertisement: { + _id: '65844efc814dd4003db811c4', + __typename: 'Advertisement', + }, + }, + }, +}; + +const ORGANIZATIONS_LIST_MOCK = { + request: { + query: ORGANIZATIONS_LIST, + variables: { + id: 'undefined', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'undefined', + image: '', + creator: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + name: 'name', + description: 'description', + isPublic: true, + + visibleInSearch: true, + location: 'location', + members: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + admins: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + membershipRequests: { + _id: 'id', + user: { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + blockedUsers: { + _id: 'id', + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + }, + }, + ], + }, + }, +}; + +describe('Testing Advertisement Component', () => { + test('Testing if the deletion works', async () => { + const mocks = [ + { + request: { + query: ADVERTISEMENTS_GET, + }, + result: { + data: { + getAdvertisements: [ + { + _id: '1', + name: 'Advertisement1', + type: 'POPUP', + orgId: 'undefined', + link: 'http://example1.com', + endDate: '2023-01-01', + startDate: '2022-01-01', + }, + ], + }, + loading: false, + }, + }, + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, + ]; + + render( + + + + + + + + + + + ); + + await wait(); + + await act(async () => { + await userEvent.click(screen.getByText('Delete')); + }); + await act(async () => { + await userEvent.click(screen.getByText('Yes')); + }); + }); + + test('for creating new Advertisements', async () => { + const mocks = [ + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, + { + request: { + query: ADVERTISEMENTS_GET, + }, + result: { + data: { + getAdvertisements: [], + }, + loading: false, + }, + }, + ]; + + render( + + + + + + + + + + + ); + + await wait(); + + await userEvent.click(screen.getByText('Create new advertisement')); + userEvent.type( + screen.getByLabelText('Enter name of Advertisement'), + 'Cookie Shop' + ); + userEvent.type( + screen.getByLabelText('Provide a link for content to be displayed'), + 'http://yourwebsite.com/photo' + ); + userEvent.selectOptions( + screen.getByLabelText('Select type of Advertisement'), + 'POPUP' + ); + userEvent.type(screen.getByLabelText('Select Start Date'), '2023-01-01'); + userEvent.type(screen.getByLabelText('Select End Date'), '2023-02-02'); + + await userEvent.click(screen.getByTestId('addonregister')); + expect( + await screen.findByText('Advertisement created successfully') + ).toBeInTheDocument(); + }); + + test('if the component renders correctly and ads are correctly categorized date wise', async () => { + const mocks = [ + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, + { + request: { + query: ADVERTISEMENTS_GET, + }, + result: { + data: { + getAdvertisements: [ + { + _id: '1', + name: 'Advertisement1', + type: 'POPUP', + orgId: 'undefined', + link: 'http://example1.com', + endDate: '2023-01-01', + startDate: '2022-01-01', + }, + ], + }, + loading: false, + }, + }, + ]; + + render( - {} + + + ); - expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + + await wait(); + + const date = await screen.findAllByText(/Ends/i); + const dateString = date[0].innerHTML; + const dateMatch = dateString.match( + /\b(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{1,2})\s+(\d{4})\b/ + ); + let dateObject = new Date(); + + if (dateMatch) { + const monthName = dateMatch[1]; + const day = parseInt(dateMatch[2], 10); + const year = parseInt(dateMatch[3], 10); + + const monthIndex = + 'JanFebMarAprMayJunJulAugSepOctNovDec'.indexOf(monthName) / 3; + + dateObject = new Date(year, monthIndex, day); + } + + expect(dateObject.getTime()).toBeLessThan(new Date().getTime()); }); - test('renders advertisement data', async () => { + test('for the working of the tabs', async () => { const mocks = [ + ORGANIZATIONS_LIST_MOCK, + PLUGIN_GET_MOCK, + ADD_ADVERTISEMENT_MUTATION_MOCK, { request: { query: ADVERTISEMENTS_GET, - variables: { - name: 'Test', - }, }, result: { data: { getAdvertisements: [ { _id: '1', - name: 'Advertisement', + name: 'Advertisement1', type: 'POPUP', - orgId: 'org1', - link: 'http://example.com', - endDate: new Date(), - startDate: new Date(), + orgId: 'undefined', + link: 'http://example1.com', + endDate: '2023-01-01', + startDate: '2022-01-01', + }, + { + _id: '2', + name: 'Advertisement2', + type: 'BANNER', + orgId: 'undefined', + link: 'http://example2.com', + endDate: tomorrow, + startDate: today, }, - // Add more mock data if needed ], }, loading: false, @@ -76,7 +371,7 @@ describe('Testing Advertisement Component', () => { }, ]; - const { getByTestId } = render( + render( @@ -90,6 +385,10 @@ describe('Testing Advertisement Component', () => { ); - expect(getByTestId('AdEntryStore')).toBeInTheDocument(); + await wait(); + userEvent.click(screen.getByText('Active Campaigns')); + + await wait(); + userEvent.click(screen.getByText('Completed Campaigns')); }); }); diff --git a/src/components/Advertisements/Advertisements.tsx b/src/components/Advertisements/Advertisements.tsx index 7af6fd98c9..606a65c7e1 100644 --- a/src/components/Advertisements/Advertisements.tsx +++ b/src/components/Advertisements/Advertisements.tsx @@ -63,7 +63,7 @@ export default function advertisements(): JSX.Element { const updateLinks = async (links: any[]): Promise => { store.dispatch({ type: 'UPDATE_P_TARGETS', payload: links }); }; - // /* istanbul ignore next */ + /* istanbul ignore next */ const pluginModified = (): void => { return getInstalledPlugins(); // .then((installedPlugins) => { @@ -77,6 +77,7 @@ export default function advertisements(): JSX.Element { isStore ? getStorePlugins() : getInstalledPlugins(); }; + /* istanbul ignore next */ const filterChange = (ev: any): void => { setShowEnabled(ev.target.value === 'enabled'); }; @@ -140,6 +141,7 @@ export default function advertisements(): JSX.Element { orgId={ad.orgId} startDate={new Date(ad.startDate)} endDate={new Date(ad.endDate)} + link={ad.link} // getInstalledPlugins={getInstalledPlugins} /> ) diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css index 1f1ea89996..20bb86a21a 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.module.css @@ -4,13 +4,12 @@ } .entryaction { - margin-left: auto; display: flex !important; - align-items: center; } .entryaction i { margin-right: 8px; + margin-top: 4px; } .entryaction .spinner-grow { @@ -18,3 +17,54 @@ width: 1rem; margin-right: 8px; } + +.buttons { + display: flex; + justify-content: flex-end; +} + +.dropdownButton { + background-color: transparent; + color: #000; + border: none; + cursor: pointer; + display: flex; + width: 100%; + justify-content: flex-end; + padding: 8px 10px; +} + +.dropdownContainer { + position: relative; + display: inline-block; +} + +.dropdownmenu { + display: none; + position: absolute; + z-index: 1; + background-color: white; + width: 120px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + padding: 5px 0; + margin: 0; + list-style-type: none; + right: 0; + top: 100%; +} + +.dropdownmenu li { + cursor: pointer; + padding: 8px 16px; + text-decoration: none; + display: block; + color: #333; +} + +.dropdownmenu li:hover { + background-color: #f1f1f1; +} + +.dropdownContainer:hover .dropdownmenu { + display: block; +} diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx index bedd1c1ce9..429298ed6a 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; +import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations'; +import { MockedProvider } from '@apollo/client/testing'; import { render, fireEvent, waitFor, screen } from '@testing-library/react'; - import { ApolloClient, ApolloProvider, @@ -8,7 +9,7 @@ import { ApolloLink, HttpLink, } from '@apollo/client'; - +import { StaticMockLink } from 'utils/StaticMockLink'; import type { NormalizedCacheObject } from '@apollo/client'; import { BrowserRouter } from 'react-router-dom'; import AdvertisementEntry from './AdvertisementEntry'; @@ -17,7 +18,71 @@ import { store } from 'state/store'; import { BACKEND_URL } from 'Constant/constant'; import i18nForTest from 'utils/i18nForTest'; import { I18nextProvider } from 'react-i18next'; +import { act } from 'react-dom/test-utils'; +import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; + +const advertisementProps = { + id: '1', + name: 'Sample Advertisement', + type: 'Sample Type', + orgId: 'org_id', + link: 'samplelink.com', + endDate: new Date(), + startDate: new Date(), +}; +const mocks = [ + { + request: { + query: DELETE_ADVERTISEMENT_BY_ID, + variables: { id: '1' }, + }, + result: { + data: { + deleteAdvertisementById: { + success: true, + }, + }, + }, + }, + { + request: { + query: ADVERTISEMENTS_GET, + }, + result: { + data: { + getAdvertisements: [ + { + _id: '6574cf9caa18987e28d248d9', + name: 'Cookie', + orgId: '6437904485008f171cf29924', + link: '123', + type: 'BANNER', + startDate: '2023-12-10', + endDate: '2023-12-10', + }, + { + _id: '6574e38aaa18987e28d24979', + name: 'HEy', + orgId: '6437904485008f171cf29924', + link: '123', + type: 'BANNER', + startDate: '2023-12-10', + endDate: '2023-12-10', + }, + ], + }, + }, + }, +]; +const link = new StaticMockLink(mocks, true); +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} const httpLink = new HttpLink({ uri: BACKEND_URL, headers: { @@ -113,4 +178,69 @@ describe('Testing Advertisement Entry Component', () => { expect(deletionFailedText).toBeNull(); }); }); + it('should open and close the dropdown when options button is clicked', () => { + const { getByTestId, queryByText, getAllByText } = render( + + + + + + + + + + ); + + // Test initial rendering + expect(getByTestId('AdEntry')).toBeInTheDocument(); + expect(getAllByText('POPUP')[0]).toBeInTheDocument(); + expect(getAllByText('Advert1')[0]).toBeInTheDocument(); + + // Test dropdown functionality + const optionsButton = getByTestId('moreiconbtn'); + + // Initially, the dropdown should not be visible + expect(queryByText('Edit')).toBeNull(); + + // Click to open the dropdown + fireEvent.click(optionsButton); + + // After clicking the button, the dropdown should be visible + expect(queryByText('Edit')).toBeInTheDocument(); + + // Click again to close the dropdown + fireEvent.click(optionsButton); + + // After the second click, the dropdown should be hidden again + expect(queryByText('Edit')).toBeNull(); + }); + test('should delete an advertisement when delete button is clicked', async () => { + const { getByTestId } = render( + + + + + + + + + + + + ); + await wait(); + const optionsButton = getByTestId('moreiconbtn'); + fireEvent.click(optionsButton); + const deleteButton = getByTestId('deletebtn'); + fireEvent.click(deleteButton); + }); }); diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx index 3f932ad848..ca665e8ca1 100644 --- a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx +++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.tsx @@ -6,6 +6,8 @@ import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations'; import { useMutation } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; +import AdvertisementRegister from '../AdvertisementRegister/AdvertisementRegister'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; import { toast } from 'react-toastify'; interface InterfaceAddOnEntryProps { id: string; @@ -29,8 +31,8 @@ function advertisementEntry({ }: InterfaceAddOnEntryProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); const [buttonLoading, setButtonLoading] = useState(false); + const [dropdown, setDropdown] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); - const [deleteAdById] = useMutation(DELETE_ADVERTISEMENT_BY_ID, { refetchQueries: [ADVERTISEMENTS_GET], }); @@ -51,12 +53,43 @@ function advertisementEntry({ setButtonLoading(false); } }; + const handleOptionsClick = (): void => { + setDropdown(!dropdown); + }; return ( <> {Array.from({ length: 1 }).map((_, idx) => ( +
+ + {dropdown && ( +
    +
  • + +
  • +
  • + {t('delete')} +
  • +
+ )} +
{type} + {link} +
+ +
{link} -
diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css index c122d386fa..646311041a 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.module.css @@ -4,6 +4,16 @@ align-items: center; } -.modalbtn i { +.modalbtn i, +.button i { margin-right: 8px; } + +.button { + min-width: 102px; +} + +.editHeader { + background-color: #31bb6b; + color: white; +} diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx index 5d9f4e00a7..9a578c114c 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.test.tsx @@ -211,12 +211,7 @@ describe('Testing Advertisement Register Component', () => { expect(setTimeoutSpy).toHaveBeenCalled(); }); - await waitFor( - () => { - expect(window.location.reload).toHaveBeenCalled(); - }, - { timeout: 2500 } - ); + expect(queryByText(translations.close)).not.toBeInTheDocument(); }); test('Logs error to the console and shows error toast when advertisement creation fails', async () => { const { getByText, queryByText } = render( diff --git a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx index e1a980150c..3686c20f31 100644 --- a/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx +++ b/src/components/Advertisements/core/AdvertisementRegister/AdvertisementRegister.tsx @@ -1,16 +1,28 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import styles from './AdvertisementRegister.module.css'; import { Button, Form, Modal } from 'react-bootstrap'; -import { useMutation } from '@apollo/client'; -import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + ADD_ADVERTISEMENT_MUTATION, + UPDATE_ADVERTISEMENT_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { useMutation, useQuery } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import dayjs from 'dayjs'; +import { ADVERTISEMENTS_GET } from 'GraphQl/Queries/Queries'; interface InterfaceAddOnRegisterProps { id?: string; // OrgId createdBy?: string; // User + formStatus?: string; + idEdit?: string; + nameEdit?: string; + typeEdit?: string; + orgIdEdit?: string; + linkEdit?: string; + endDateEdit?: Date; + startDateEdit?: Date; } interface InterfaceFormStateTypes { name: string; @@ -24,6 +36,16 @@ interface InterfaceFormStateTypes { function advertisementRegister({ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ createdBy, + formStatus, + idEdit, + nameEdit, + typeEdit, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + orgIdEdit, + linkEdit, + endDateEdit, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + startDateEdit, }: InterfaceAddOnRegisterProps): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'advertisement' }); @@ -32,6 +54,8 @@ function advertisementRegister({ const handleClose = (): void => setShow(false); const handleShow = (): void => setShow(true); const [create] = useMutation(ADD_ADVERTISEMENT_MUTATION); + const [updateAdvertisement] = useMutation(UPDATE_ADVERTISEMENT_MUTATION); + const { refetch } = useQuery(ADVERTISEMENTS_GET); //getting orgId from URL const currentOrg = window.location.href.split('/id=')[1] + ''; @@ -43,6 +67,30 @@ function advertisementRegister({ endDate: new Date(), orgId: currentOrg, }); + + //if set to edit set the formState by edit variables + useEffect(() => { + if (formStatus === 'edit') { + setFormState((prevState) => ({ + ...prevState, + name: nameEdit || '', + link: linkEdit || '', + type: typeEdit || 'BANNER', + startDate: startDateEdit || new Date(), + endDate: endDateEdit || new Date(), + orgId: currentOrg, + })); + } + }, [ + formStatus, + nameEdit, + linkEdit, + typeEdit, + startDateEdit, + endDateEdit, + currentOrg, + ]); + const handleRegister = async (): Promise => { try { console.log('At handle register', formState); @@ -59,29 +107,66 @@ function advertisementRegister({ if (data) { toast.success('Advertisement created successfully'); - setTimeout(() => { - window.location.reload(); - }, 2000); + refetch(); + setFormState({ + name: '', + link: '', + type: 'BANNER', + startDate: new Date(), + endDate: new Date(), + orgId: currentOrg, + }); + handleClose(); } } catch (error) { toast.error('An error occured, could not create new advertisement'); console.log('error occured', error); } }; + const handleUpdate = async (): Promise => { + try { + console.log('At handle update', formState); + const { data } = await updateAdvertisement({ + variables: { + id: idEdit, + // orgId: currentOrg, + name: formState.name, + link: formState.link, + type: formState.type, + startDate: dayjs(formState.startDate).format('YYYY-MM-DD'), + endDate: dayjs(formState.endDate).format('YYYY-MM-DD'), + }, + }); + + if (data) { + toast.success('Advertisement updated successfully'); + } + } catch (error: any) { + toast.error(error.message); + } + }; return ( <> - + {formStatus === 'register' ? ( //If register show register button else show edit button + + ) : ( +
{t('edit')}
+ )} - - {t('RClose')} + + {formStatus === 'register' ? ( + {t('RClose')} + ) : ( + {t('editAdvertisement')} + )}
@@ -140,7 +225,7 @@ function advertisementRegister({ { setFormState({ ...formState, @@ -155,7 +240,7 @@ function advertisementRegister({ { setFormState({ ...formState, @@ -174,13 +259,23 @@ function advertisementRegister({ > {t('close')} - + {formStatus === 'register' ? ( + + ) : ( + + )} @@ -194,6 +289,7 @@ advertisementRegister.defaultProps = { startDate: new Date(), endDate: new Date(), orgId: '', + formStatus: 'register', }; advertisementRegister.propTypes = { @@ -203,6 +299,7 @@ advertisementRegister.propTypes = { startDate: PropTypes.instanceOf(Date), endDate: PropTypes.instanceOf(Date), orgId: PropTypes.string, + formStatus: PropTypes.string, }; export default advertisementRegister; diff --git a/src/components/IconComponent/IconComponent.test.tsx b/src/components/IconComponent/IconComponent.test.tsx index ff83ebe57c..a66866b2ad 100644 --- a/src/components/IconComponent/IconComponent.test.tsx +++ b/src/components/IconComponent/IconComponent.test.tsx @@ -32,8 +32,8 @@ const screenTestIdMap: Record> = { testId: 'Icon-Component-SettingsIcon', }, AllOrganizations: { - name: 'All Organizations', - testId: 'Icon-Component-AllOrganizationsIcon', + name: 'My Organizations', + testId: 'Icon-Component-MyOrganizationsIcon', }, EventProject: { name: 'Add Event Project', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 4c490c9c94..891b08d9ee 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -22,6 +22,13 @@ export interface InterfaceIconComponent { const iconComponent = (props: InterfaceIconComponent): JSX.Element => { switch (props.name) { + case 'My Organizations': + return ( + + ); case 'Dashboard': return ( @@ -53,13 +60,6 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { data-testid="Icon-Component-SettingsIcon" /> ); - case 'All Organizations': - return ( - - ); case 'Add Event Project': return ( { ); - expect(screen.getByText('Organizations')).toBeInTheDocument(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Requests')).toBeInTheDocument(); expect(screen.getByText('Users')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); @@ -231,7 +231,7 @@ describe('Testing Left Drawer component for ADMIN', () => { ); - expect(screen.getByText('Organizations')).toBeInTheDocument(); + expect(screen.getByText('My Organizations')).toBeInTheDocument(); expect(screen.getByText('Talawa Admin Portal')).toBeInTheDocument(); expect(screen.getByText(/John Doe/i)).toBeInTheDocument(); diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index d2fdfedbcb..224cfeb2ec 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -67,9 +67,11 @@ const leftDrawer = ({
{t('menu')}
{userType === 'SUPERADMIN' && (