From 62cf1b832b5b67cfd6d304158c811b98ef494b27 Mon Sep 17 00:00:00 2001 From: Abhishek P Anil Date: Mon, 4 Dec 2023 15:51:42 +0530 Subject: [PATCH 1/4] fix: added duplicate remove utils function to remove duplicate objects from array --- src/utils/removeObjectArrayDuplicates.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/utils/removeObjectArrayDuplicates.js diff --git a/src/utils/removeObjectArrayDuplicates.js b/src/utils/removeObjectArrayDuplicates.js new file mode 100644 index 00000000..521469c8 --- /dev/null +++ b/src/utils/removeObjectArrayDuplicates.js @@ -0,0 +1,11 @@ +export const removeObjectArrayDuplicates = (array, key = 'id') => { + let uniqueIds = new Set(); + let uniqueArray = array.filter((obj) => { + if (!uniqueIds.has(obj[key])) { + uniqueIds.add(obj[key]); + return true; + } + return false; + }); + return uniqueArray; +}; From 3dbb37bbf11f07605b08a5d50da09f3591ce2653 Mon Sep 17 00:00:00 2001 From: Abhishek P Anil Date: Mon, 4 Dec 2023 15:52:19 +0530 Subject: [PATCH 2/4] fix: added ids filter to get all orgs api --- src/services/organization.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/organization.js b/src/services/organization.js index 094891c9..6100f3be 100644 --- a/src/services/organization.js +++ b/src/services/organization.js @@ -26,8 +26,8 @@ export const organizationApi = createApi({ }), }), getAllOrganization: builder.query({ - query: ({ calendarId, pageNumber = 1, limit = 10, query = '', sort = 'sort=asc(name.en)' }) => ({ - url: `organizations?page=${pageNumber}&limit=${limit}&search=${query}&${sort}`, + query: ({ calendarId, pageNumber = 1, limit = 10, query = '', sort = 'sort=asc(name.en)', ids = '' }) => ({ + url: `organizations?page=${pageNumber}&limit=${limit}&search=${query}&${sort}&${ids}`, method: 'GET', headers: { 'calendar-id': calendarId, From b4b94645d673c3c06c301393e43886abff9332ea Mon Sep 17 00:00:00 2001 From: Abhishek P Anil Date: Tue, 5 Dec 2023 12:11:25 +0530 Subject: [PATCH 3/4] fix: added checked orgs filter to stay after refresh and search --- .../SearchableCheckbox/SearchableCheckbox.jsx | 4 +- src/pages/Dashboard/Events/Events.jsx | 70 +++++++++++++++---- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/components/Filter/SearchableCheckbox/SearchableCheckbox.jsx b/src/components/Filter/SearchableCheckbox/SearchableCheckbox.jsx index 15c0de71..42f2a3ab 100644 --- a/src/components/Filter/SearchableCheckbox/SearchableCheckbox.jsx +++ b/src/components/Filter/SearchableCheckbox/SearchableCheckbox.jsx @@ -13,8 +13,8 @@ function SearchableCheckbox(props) { let items = data ?? []; useEffect(() => { - if (allowSearch) { - props.searchImplementation(); + if (allowSearch && props?.searchKey != undefined) { + props.searchImplementation(props?.searchKey); } }, [props.searchKey]); diff --git a/src/pages/Dashboard/Events/Events.jsx b/src/pages/Dashboard/Events/Events.jsx index 6873623d..2f3d0f09 100644 --- a/src/pages/Dashboard/Events/Events.jsx +++ b/src/pages/Dashboard/Events/Events.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react'; +import React, { useEffect, useState, useRef, useCallback } from 'react'; import './events.css'; import { Checkbox, Col, Row, Badge, Button, Dropdown, Space, Popover, Divider } from 'antd'; import { CloseCircleOutlined, DownOutlined, SortAscendingOutlined, SortDescendingOutlined } from '@ant-design/icons'; @@ -28,6 +28,9 @@ import NoContent from '../../../components/NoContent/NoContent'; import LoadingIndicator from '../../../components/LoadingIndicator/index'; import { contentLanguageBilingual } from '../../../utils/bilingual'; import { useLazyGetAllOrganizationQuery } from '../../../services/organization'; +import { removeObjectArrayDuplicates } from '../../../utils/removeObjectArrayDuplicates'; +import { SEARCH_DELAY } from '../../../constants/search'; +import { useDebounce } from '../../../hooks/debounce'; function Events() { const { t } = useTranslation(); @@ -39,10 +42,9 @@ function Events() { const [currentCalendarData, pageNumber, setPageNumber] = useOutletContext(); const [getEvents, { currentData: eventsData, isLoading, isFetching }] = useLazyGetEventsQuery(); - const [getAllUsers, { currentData: allUsersData, isLoading: allUsersLoading }] = useLazyGetAllUsersQuery(); + const [getAllUsers, { currentData: allUsersData, isFetching: allUsersLoading }] = useLazyGetAllUsersQuery(); - const [getAllOrganization, { currentData: organizersData, isLoading: organizerLoading }] = - useLazyGetAllOrganizationQuery(); + const [getAllOrganization, { isFetching: organizerLoading }] = useLazyGetAllOrganizationQuery(); const [searchKey, setSearchKey] = useState(); const [organizationSearchKey, setOrganizationSearchKey] = useState(); @@ -116,12 +118,14 @@ function Events() { } for (let index = 0; index < organizerFilter?.length; index++) { - Object.assign(initialSelectedUsers, { [userFilter[index]]: true }); + Object.assign(initialSelectedOrganizers, { [organizerFilter[index]]: true }); } - + let selectedOrganizersData = []; const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [selectedUsers, setSelectedUsers] = useState(initialSelectedUsers ?? {}); const [selectedOrganizer, setSelectedOrganizers] = useState(initialSelectedOrganizers ?? {}); + const [organizersData, setOrganizersData] = useState([]); + const [selectedDates, setSelectedDates] = useState( (searchParams.get('startDateRange') || sessionStorage.getItem('startDateRange')) && (searchParams.get('endDateRange') || sessionStorage.getItem('endDateRange')) @@ -167,17 +171,24 @@ function Events() { }); }; - const organizersPersonPlaceSearch = () => { + const organizersPersonPlaceSearch = (searchKey) => { getAllOrganization({ calendarId, sessionId: timestampRef, pageNumber: 1, - query: organizationSearchKey, + query: searchKey, sort: `sort=asc(${sortByOptionsOrgsPlacesPerson[0]?.key})`, - }); + }) + .unwrap() + .then((response) => { + let uniqueArray = removeObjectArrayDuplicates(selectedOrganizersData?.concat(response?.data), 'id'); + setOrganizersData(uniqueArray); + }) + .catch((error) => console.log(error)); }; const calendarContentLanguage = currentCalendarData?.contentLanguage; + const debounceSearchOrganizationSearch = useCallback(useDebounce(organizersPersonPlaceSearch, SEARCH_DELAY), []); useEffect(() => { let query = new URLSearchParams(); @@ -268,8 +279,9 @@ function Events() { }, [calendarId, pageNumber, eventSearchQuery, filter, userFilter, organizerFilter]); useEffect(() => { + let allOrganizersWithSelected = []; getAllUsers({ - page: pageNumber, + page: 1, limit: 30, query: '', filters: `sort=asc(${sortByOptionsUsers[1].key})`, @@ -282,9 +294,35 @@ function Events() { limit: 30, sessionId: timestampRef, pageNumber: 1, - query: organizationSearchKey, + query: '', sort: `sort=asc(${sortByOptionsOrgsPlacesPerson[0]?.key})`, - }); + }) + .unwrap() + .then((response) => { + allOrganizersWithSelected = response?.data; + if (organizerFilter?.length > 0) { + let organizerIds = new URLSearchParams(); + organizerFilter?.forEach((organizerId) => organizerIds.append('ids', organizerId)); + getAllOrganization({ + calendarId, + limit: 30, + sessionId: timestampRef, + pageNumber: 1, + query: '', + sort: `sort=asc(${sortByOptionsOrgsPlacesPerson[0]?.key})`, + ids: organizerIds, + }) + .unwrap() + .then((response) => { + selectedOrganizersData = response?.data; + allOrganizersWithSelected = response?.data?.concat(allOrganizersWithSelected); + let uniqueArray = removeObjectArrayDuplicates(allOrganizersWithSelected, 'id'); + setOrganizersData(uniqueArray); + }) + .catch((error) => console.log(error)); + } else setOrganizersData(allOrganizersWithSelected); + }) + .catch((error) => console.log(error)); }, [calendarId]); const onSearchHandler = (event) => { @@ -315,6 +353,10 @@ function Events() { let filteredOrganizers = Object.keys(currentOrganizerFilter).filter(function (key) { return currentOrganizerFilter[key]; }); + selectedOrganizersData = organizersData?.filter((organizerData) => { + if (filteredOrganizers?.includes(organizerData?.id)) return true; + else return false; + }); setOrganizerFilter(filteredOrganizers); setPageNumber(1); }; @@ -618,10 +660,10 @@ function Events() { allowSearch={true} loading={organizerLoading} overlayStyle={{ height: '304px' }} - searchImplementation={organizersPersonPlaceSearch} + searchImplementation={debounceSearchOrganizationSearch} setSearchKey={setOrganizationSearchKey} searchKey={organizationSearchKey} - data={organizersData?.data?.map((organizer) => { + data={organizersData?.map((organizer) => { return { key: organizer?.id, label: ( From efdfd63f506cfb7ddb9a348a8bd9254d74a48b1e Mon Sep 17 00:00:00 2001 From: Abhishek P Anil Date: Tue, 5 Dec 2023 16:42:40 +0530 Subject: [PATCH 4/4] fix: added user filter by ids and implementation. closes #819 --- src/pages/Dashboard/Events/Events.jsx | 83 ++++++++++++++++++++------- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/src/pages/Dashboard/Events/Events.jsx b/src/pages/Dashboard/Events/Events.jsx index 2f3d0f09..89a65038 100644 --- a/src/pages/Dashboard/Events/Events.jsx +++ b/src/pages/Dashboard/Events/Events.jsx @@ -42,7 +42,7 @@ function Events() { const [currentCalendarData, pageNumber, setPageNumber] = useOutletContext(); const [getEvents, { currentData: eventsData, isLoading, isFetching }] = useLazyGetEventsQuery(); - const [getAllUsers, { currentData: allUsersData, isFetching: allUsersLoading }] = useLazyGetAllUsersQuery(); + const [getAllUsers, { isFetching: allUsersLoading }] = useLazyGetAllUsersQuery(); const [getAllOrganization, { isFetching: organizerLoading }] = useLazyGetAllOrganizationQuery(); @@ -120,11 +120,13 @@ function Events() { for (let index = 0; index < organizerFilter?.length; index++) { Object.assign(initialSelectedOrganizers, { [organizerFilter[index]]: true }); } - let selectedOrganizersData = []; + let selectedOrganizersData = [], + selectedUsersData = []; const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [selectedUsers, setSelectedUsers] = useState(initialSelectedUsers ?? {}); const [selectedOrganizer, setSelectedOrganizers] = useState(initialSelectedOrganizers ?? {}); const [organizersData, setOrganizersData] = useState([]); + const [usersData, setUsersData] = useState([]); const [selectedDates, setSelectedDates] = useState( (searchParams.get('startDateRange') || sessionStorage.getItem('startDateRange')) && @@ -156,19 +158,27 @@ function Events() { // return x?._id == user?.id ? -1 : y?._id == user?.id ? 1 : 0; // }); - let userFilterData = allUsersData?.data?.filter((item) => user?.id != item._id); - userFilterData = [{ _id: user?.id, ...user }]?.concat(userFilterData); + // let userFilterData = allUsersData?.data?.filter((item) => user?.id != item._id); + // userFilterData = [{ _id: user?.id, ...user }]?.concat(userFilterData); - const userSearch = () => { + console.log(user); + const userSearch = (userSearchKey) => { getAllUsers({ page: pageNumber, limit: 30, - query: searchKey, + query: userSearchKey, filters: `sort=asc(${sortByOptionsUsers[1].key})`, sessionId: timestampRef, calendarId: calendarId, includeCalenderFilter: true, - }); + }) + .then((response) => { + let currentUserList = selectedUsersData?.concat(response?.data?.data); + currentUserList = [{ _id: user?.id, ...user }]?.concat(currentUserList); + let uniqueArray = removeObjectArrayDuplicates(currentUserList, '_id'); + setUsersData(uniqueArray); + }) + .catch((error) => console.log(error)); }; const organizersPersonPlaceSearch = (searchKey) => { @@ -189,6 +199,7 @@ function Events() { const calendarContentLanguage = currentCalendarData?.contentLanguage; const debounceSearchOrganizationSearch = useCallback(useDebounce(organizersPersonPlaceSearch, SEARCH_DELAY), []); + const debounceUsersSearch = useCallback(useDebounce(userSearch, SEARCH_DELAY), []); useEffect(() => { let query = new URLSearchParams(); @@ -279,16 +290,48 @@ function Events() { }, [calendarId, pageNumber, eventSearchQuery, filter, userFilter, organizerFilter]); useEffect(() => { - let allOrganizersWithSelected = []; - getAllUsers({ - page: 1, - limit: 30, - query: '', - filters: `sort=asc(${sortByOptionsUsers[1].key})`, - sessionId: timestampRef, - calendarId: calendarId, - includeCalenderFilter: true, - }); + let allOrganizersWithSelected = [], + allUsersWithSelected = []; + if (calendarId) + if (user?.id !== '' && user?.id) { + getAllUsers({ + page: 1, + limit: 30, + query: '', + filters: `sort=asc(${sortByOptionsUsers[1].key})`, + sessionId: timestampRef, + calendarId: calendarId, + includeCalenderFilter: true, + }) + .unwrap() + .then((response) => { + allUsersWithSelected = [{ _id: user?.id, ...user }]?.concat(response?.data); + allUsersWithSelected = removeObjectArrayDuplicates(allUsersWithSelected, '_id'); + if (userFilter?.length > 0) { + let userIds = new URLSearchParams(); + userFilter?.forEach((userId) => userIds.append('ids', userId)); + getAllUsers({ + page: 1, + limit: 30, + query: '', + filters: `sort=asc(${sortByOptionsUsers[1].key})&${userIds}`, + sessionId: timestampRef, + calendarId: calendarId, + includeCalenderFilter: true, + }) + .unwrap() + .then((response) => { + selectedUsersData = response?.data; + allUsersWithSelected = response?.data?.concat(allUsersWithSelected); + allUsersWithSelected = [{ _id: user?.id, ...user }]?.concat(allUsersWithSelected); + let uniqueArray = removeObjectArrayDuplicates(allUsersWithSelected, '_id'); + setUsersData(uniqueArray); + }) + .catch((error) => console.log(error)); + } else setUsersData(allUsersWithSelected); + }) + .catch((error) => console.log(error)); + } getAllOrganization({ calendarId, limit: 30, @@ -323,7 +366,7 @@ function Events() { } else setOrganizersData(allOrganizersWithSelected); }) .catch((error) => console.log(error)); - }, [calendarId]); + }, [calendarId, user]); const onSearchHandler = (event) => { setPageNumber(1); @@ -549,10 +592,10 @@ function Events() { allowSearch={true} loading={allUsersLoading} overlayStyle={{ height: '304px' }} - searchImplementation={userSearch} + searchImplementation={debounceUsersSearch} setSearchKey={setSearchKey} searchKey={searchKey} - data={userFilterData?.map((userDetail) => { + data={usersData?.map((userDetail) => { return { key: userDetail?._id, label: (