From b01caca9becf84a29c44e6251f13ecbe9a27fe67 Mon Sep 17 00:00:00 2001 From: Ochieng Paul Date: Mon, 20 Nov 2023 02:13:38 +0300 Subject: [PATCH 01/38] worked on checklist completion --- .../components/Charts/ChartContainer.js | 2 +- .../src/common/components/Customise/index.jsx | 4 ++- .../src/common/components/Layout/index.jsx | 2 +- .../components/Modal/PrintReportModal.jsx | 15 ++++----- platform/src/pages/Home/index.jsx | 33 +++++++++++-------- platform/src/pages/analytics/index.jsx | 8 ++--- 6 files changed, 34 insertions(+), 30 deletions(-) diff --git a/platform/src/common/components/Charts/ChartContainer.js b/platform/src/common/components/Charts/ChartContainer.js index f56c6e587d..ecf9ef767d 100644 --- a/platform/src/common/components/Charts/ChartContainer.js +++ b/platform/src/common/components/Charts/ChartContainer.js @@ -210,7 +210,7 @@ const ChartContainer = ({ chartType, chartTitle, menuBtn, height, width, id, dow setOpenShare(false)} format={shareFormat} diff --git a/platform/src/common/components/Customise/index.jsx b/platform/src/common/components/Customise/index.jsx index 01a33083cb..95828d4600 100644 --- a/platform/src/common/components/Customise/index.jsx +++ b/platform/src/common/components/Customise/index.jsx @@ -9,6 +9,7 @@ import { } from '@/lib/store/services/account/UserDefaultsSlice'; import Toast from '@/components/Toast'; import { fetchUserPreferences } from '@/lib/store/services/charts/userDefaultsSlice'; +import { completeTask } from '@/lib/store/services/checklists/CheckList'; const CustomiseLocationsComponent = ({ toggleCustomise }) => { const dispatch = useDispatch(); @@ -21,7 +22,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { const selectedLocations = useSelector((state) => state.grids.selectedLocations) || []; const preferenceData = useSelector((state) => state.defaults.individual_preferences) || []; const customisedLocations = - preferenceData.length > 0 ? preferenceData[0].selected_sites.slice(0, 4) : []; + preferenceData.length > 0 ? preferenceData[0].selected_sites.slice(-4) : []; const id = useSelector((state) => state.login.userInfo._id); const chartData = useSelector((state) => state.chart); @@ -67,6 +68,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { toggleCustomise(); // fetching user preferences after update dispatch(fetchUserPreferences(id)); + dispatch(completeTask(2)); } } catch (error) { throw error; diff --git a/platform/src/common/components/Layout/index.jsx b/platform/src/common/components/Layout/index.jsx index 66d33d69dc..f3272805bf 100644 --- a/platform/src/common/components/Layout/index.jsx +++ b/platform/src/common/components/Layout/index.jsx @@ -53,7 +53,7 @@ const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorder ? selected_sites.map((site) => site['_id']) : chartData.chartSites; - await dispatch(setChartSites(chartSites.slice(0, 4))); + await dispatch(setChartSites(chartSites.slice(-4))); await dispatch( setChartDataRange({ startDate: startDate || chartData.chartDataRange.startDate, diff --git a/platform/src/common/components/Modal/PrintReportModal.jsx b/platform/src/common/components/Modal/PrintReportModal.jsx index 11d906db4e..d125bc6558 100644 --- a/platform/src/common/components/Modal/PrintReportModal.jsx +++ b/platform/src/common/components/Modal/PrintReportModal.jsx @@ -20,7 +20,7 @@ const PrintReportModal = ({ title, format, btnText, - ModalType = 'share', + shareModel, shareStatus, }) => { const [loading, setLoading] = useState(false); @@ -245,13 +245,12 @@ const PrintReportModal = ({ onClose; handleCancel(); }} - downloadDataFunc={ModalType === 'share' ? handleShareReport : handleDataExport} + downloadDataFunc={shareModel ? handleShareReport : handleDataExport} loading={loading} ModalIcon={ShareIcon} primaryButtonText={btnText || 'Print'} - data={data} - > - {ModalType === 'share' && ( + data={data}> + {shareModel && ( <>
0 && ( )} @@ -298,8 +296,7 @@ const PrintReportModal = ({
diff --git a/platform/src/pages/Home/index.jsx b/platform/src/pages/Home/index.jsx index 9b27959137..385a024076 100644 --- a/platform/src/pages/Home/index.jsx +++ b/platform/src/pages/Home/index.jsx @@ -9,7 +9,7 @@ import AnalyticsImage from '@/images/Home/analyticsImage.png'; import PlayIcon from '@/images/Home/playIcon.svg'; import AnalyticsVideo from '../../../public/videos/analytics.mp4'; import { useSelector, useDispatch } from 'react-redux'; -import { startTask, updateTitle } from '@/lib/store/services/checklists/CheckList'; +import { startTask, completeTask, updateTitle } from '@/lib/store/services/checklists/CheckList'; import HomeSkeleton from '@/components/skeletons/HomeSkeleton'; import CustomModal from '@/components/Modal/videoModals/CustomModal'; import StepProgress from '@/components/steppers/CircularStepper'; @@ -48,17 +48,21 @@ const Home = () => { }; const handleCardClick = (id) => { - const card = cardCheckList.find((card) => card.id === id); - if (card) { - switch (card.status) { - case 'not started': - dispatch(startTask(id)); - break; - default: - return; - } + if (id === 4) { + dispatch(completeTask(4)); } else { - console.log('Card not found'); + const card = cardCheckList.find((card) => card.id === id); + if (card) { + switch (card.status) { + case 'not started': + dispatch(startTask(id)); + break; + default: + return; + } + } else { + console.log('Card not found'); + } } }; @@ -84,7 +88,7 @@ const Home = () => { { label: 'Practical ways to reduce air pollution', time: '1 min', - link: '#', + link: 'https://blog.airqo.net/', func: () => handleCardClick(4), }, ]; @@ -150,7 +154,10 @@ const Home = () => { ) : ( <> - + {card && card.status === 'inProgress' ? 'Resume' : statusText} diff --git a/platform/src/pages/analytics/index.jsx b/platform/src/pages/analytics/index.jsx index e741a3857e..d7d29c282c 100644 --- a/platform/src/pages/analytics/index.jsx +++ b/platform/src/pages/analytics/index.jsx @@ -151,16 +151,14 @@ const AuthenticatedHomePage = () => {
@@ -212,7 +210,7 @@ const AuthenticatedHomePage = () => { open={openPrintModal} onClose={() => setOpenPrintModal(false)} data={data} - ModalType='share' + shareModel={false} format={'pdf'} /> )} From 832336deae4449e22259bdacea6a8583b49337c3 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:33:25 +0300 Subject: [PATCH 02/38] maintain state of selected nav tab --- .../components/CleanAir/SecondaryNav/index.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/website/frontend/src/components/CleanAir/SecondaryNav/index.js b/website/frontend/src/components/CleanAir/SecondaryNav/index.js index d3674095f6..fa1f399f38 100644 --- a/website/frontend/src/components/CleanAir/SecondaryNav/index.js +++ b/website/frontend/src/components/CleanAir/SecondaryNav/index.js @@ -1,34 +1,37 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { setActiveTab } from '../../../../reduxStore/CleanAirNetwork/CleanAir'; import PropTypes from 'prop-types'; const SecondaryNavComponent = ({ disabledTabs }) => { + const tabs = ['About', 'Membership', 'Events', 'Resources']; const dispatch = useDispatch(); const activeTab = useSelector((state) => state.cleanAirData.activeTab); + const [selectedTab, setSelectedTab] = useState(tabs[0]); useEffect(() => { - dispatch(setActiveTab(0)); - }, [dispatch]); + setSelectedTab(activeTab) + }, []) - const handleTabClick = (index) => { - if (!disabledTabs.includes(index)) { - dispatch(setActiveTab(index)); + const handleTabClick = (tab) => { + if (!disabledTabs.includes(tab)) { + setSelectedTab(tab); + dispatch(setActiveTab(tab)); } }; - const tabs = ['About', 'Membership', 'Events', 'Resources']; - return (
    {tabs.map((tab, index) => (
  • handleTabClick(index)}> + className={`${selectedTab === index ? 'active' : ''} ${disabledTabs.includes(index) ? 'disabled' : '' + }`} + onClick={() => { + handleTabClick(index); + + }}> {tab}
  • ))} From 4584671d44bda5ebf15260a02974d1c767c178a4 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:34:05 +0300 Subject: [PATCH 03/38] add month to start date on event card --- .../src/components/CleanAir/Hightlights/MainHighlight.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/website/frontend/src/components/CleanAir/Hightlights/MainHighlight.js b/website/frontend/src/components/CleanAir/Hightlights/MainHighlight.js index e35a22b0f0..3498478e90 100644 --- a/website/frontend/src/components/CleanAir/Hightlights/MainHighlight.js +++ b/website/frontend/src/components/CleanAir/Hightlights/MainHighlight.js @@ -1,9 +1,8 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { getAllEvents } from '../../../../reduxStore/Events/EventSlice'; import { isEmpty } from 'underscore'; import { useNavigate } from 'react-router-dom'; -import { Link } from 'react-router-dom'; import { AccessTimeOutlined, CalendarMonth } from '@mui/icons-material'; import { format } from 'date-fns'; @@ -53,7 +52,7 @@ const Highlight = () => { {featuredEvent.end_date !== null ? ( - {format(new Date(featuredEvent.start_date), 'do')} -{' '} + {format(new Date(featuredEvent.start_date), 'do MMM')} -{' '} {format(new Date(featuredEvent.end_date), 'do MMMM yyyy')} ) : ( From 4e7a85cefeb052893f58954fac56428388006e34 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:34:31 +0300 Subject: [PATCH 04/38] separation of split section types --- .../frontend/src/components/CleanAir/Sections/SplitSection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/frontend/src/components/CleanAir/Sections/SplitSection.js b/website/frontend/src/components/CleanAir/Sections/SplitSection.js index ddaa98d7ed..5c7e093b08 100644 --- a/website/frontend/src/components/CleanAir/Sections/SplitSection.js +++ b/website/frontend/src/components/CleanAir/Sections/SplitSection.js @@ -15,10 +15,10 @@ const SplitSection = ({ imageStyle, showButton, children, - customBtn, wrapperPadding + customBtn, wrapperPadding, titleSection }) => { return ( -
    +
    {pillTitle && ( From 559d6607be93efdeee124ff01e51b63b79dcd52b Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:34:48 +0300 Subject: [PATCH 05/38] change SEO metadata --- website/frontend/src/pages/CleanAir/CleanAirAbout.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/CleanAirAbout.js b/website/frontend/src/pages/CleanAir/CleanAirAbout.js index ac4f4fd3e3..324d229cbb 100644 --- a/website/frontend/src/pages/CleanAir/CleanAirAbout.js +++ b/website/frontend/src/pages/CleanAir/CleanAirAbout.js @@ -13,8 +13,8 @@ const CleanAirAbout = () => { return (
    {/* section 1 */} From 4ceddc1fa9e48cd064b7d92b635ef399d0e93214 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:35:11 +0300 Subject: [PATCH 06/38] SEO metadata cleaning and loadspinner --- .../src/pages/CleanAir/CleanAirEvents.js | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/CleanAirEvents.js b/website/frontend/src/pages/CleanAir/CleanAirEvents.js index d67e41e106..8e7f83622e 100644 --- a/website/frontend/src/pages/CleanAir/CleanAirEvents.js +++ b/website/frontend/src/pages/CleanAir/CleanAirEvents.js @@ -11,6 +11,7 @@ import EventCard from '../Events/EventCard'; import event1 from 'assets/img/cleanAir/event-sec1.png'; import event2 from 'assets/img/cleanAir/event-sec2.png'; import useWindowSize from 'utilities/customHooks'; +import Loadspinner from 'src/components/LoadSpinner/SectionLoader'; const ITEMS_PER_PAGE = 9; @@ -78,8 +79,8 @@ const CleanAirEvents = () => { return (
    @@ -99,13 +100,13 @@ const CleanAirEvents = () => {
    -
    + {/*
    CLEAN-Air Africa Network Events
    -
    +
    */}

    @@ -138,6 +139,7 @@ const CleanAirEvents = () => { bgColor="#FFFFFF" wrapperPadding='0' reverse + titleSection={true} />
    @@ -163,16 +165,7 @@ const CleanAirEvents = () => {
    {loading ? ( -
    - loading ... -
    + ) : null} {!loading && upcomingEvents.length === 0 && selectedNavTab === 'upcoming events' ? (
    There are currently no events
    From 9556ce5b9e9786f7243f01f733b5603bd3817d1f Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:35:39 +0300 Subject: [PATCH 07/38] SEO metadata cleaning and removing partner image borders --- .../src/pages/CleanAir/CleanAirPartners.js | 98 ++++++++----------- 1 file changed, 43 insertions(+), 55 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/CleanAirPartners.js b/website/frontend/src/pages/CleanAir/CleanAirPartners.js index e89c7583e4..9e23da9ca4 100644 --- a/website/frontend/src/pages/CleanAir/CleanAirPartners.js +++ b/website/frontend/src/pages/CleanAir/CleanAirPartners.js @@ -91,8 +91,8 @@ const CleanAirPartners = () => {
    {/* SEO */} @@ -138,6 +138,7 @@ const CleanAirPartners = () => { imgURL={Partner1} bgColor="#FFFFFF" reverse + titleSection={true} /> {implementingPartners.length > 0 && ( @@ -206,25 +207,22 @@ const CleanAirPartners = () => { imgURL={Partner2} bgColor="#FFFFFF" reverse + titleSection={true} /> {policyPartners.length > 0 && ( -
    -
    -
    - - - {policyPartnerDataGroup.slice(0, itemsToShowPolicy).map((partnerGroup, key) => ( - - {partnerGroup.map((partner) => ( - - ))} - - ))} - -
    onLogoClick(partner)}> - {partner.partner_name} -
    +
    +
    +
    + {policyPartners.slice(0, itemsToShowPolicy).map((policyPartner) => ( +
    + {policyPartner.partner_name} +
    + ))} {itemsToShowPolicy < policyPartnerDataGroup.length && (
    -
    +
    Date: Tue, 21 Nov 2023 09:36:11 +0300 Subject: [PATCH 08/38] SEO metadata cleaning and styling --- .../pages/CleanAir/CleanAirPublications.js | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/CleanAirPublications.js b/website/frontend/src/pages/CleanAir/CleanAirPublications.js index d9661becd6..4acb870edc 100644 --- a/website/frontend/src/pages/CleanAir/CleanAirPublications.js +++ b/website/frontend/src/pages/CleanAir/CleanAirPublications.js @@ -4,11 +4,12 @@ import { useInitScrollTop } from 'utilities/customHooks'; import { isEmpty } from 'underscore'; import { useDispatch, useSelector } from 'react-redux'; import { setActiveResource } from 'reduxStore/CleanAirNetwork/CleanAir'; -import { CardComponent, ReportComponent } from 'components/CleanAir'; +import { ReportComponent } from 'components/CleanAir'; import { getAllCleanAirApi } from 'apis/index.js'; import ListIcon from '@mui/icons-material/List'; import CloseIcon from '@mui/icons-material/Close'; import useWindowSize from 'utilities/customHooks'; +import Loadspinner from 'src/components/LoadSpinner/SectionLoader'; const ResourceMenuItem = ({ activeResource, resource, dispatch, setToggle }) => { const { width } = useWindowSize(); @@ -99,16 +100,8 @@ const CleanAirPublications = () => { if (loading) { return ( -
    - Loading... +
    +
    ); } @@ -125,7 +118,7 @@ const CleanAirPublications = () => { alignItems: 'center', marginTop: '50px' }}> -

    No Data

    +

    No Resources available

    ); } @@ -224,14 +217,14 @@ const CleanAirPublications = () => { return (
    -
    +
    From bd1bcc6a0696a8132b4c47ac2f5463809e9ea7b7 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:36:47 +0300 Subject: [PATCH 09/38] add month ro start data --- website/frontend/src/pages/CleanAir/EventDetails.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/EventDetails.js b/website/frontend/src/pages/CleanAir/EventDetails.js index 280e4b16ed..4bb4018472 100644 --- a/website/frontend/src/pages/CleanAir/EventDetails.js +++ b/website/frontend/src/pages/CleanAir/EventDetails.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { AccessTimeOutlined, CalendarMonth, PlaceOutlined } from '@mui/icons-material'; import { useInitScrollTop } from 'utilities/customHooks'; import { useParams } from 'react-router-dom'; @@ -8,7 +8,6 @@ import { getAllEvents } from '../../../reduxStore/Events/EventSlice'; import { format } from 'date-fns'; import Loadspinner from '../../components/LoadSpinner'; import PageMini from '../PageMini'; -import { setActiveTab } from '../../../reduxStore/CleanAirNetwork/CleanAir'; const EventDetails = () => { useInitScrollTop(); @@ -67,7 +66,7 @@ const EventDetails = () => { {event.end_date !== null ? ( - {format(new Date(event.start_date), 'do')} -{' '} + {format(new Date(event.start_date), 'do MMM')} -{' '} {format(new Date(event.end_date), 'do MMMM yyyy')} ) : ( From 64740520db45e5043955958dae4f687c4e8029a9 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:37:04 +0300 Subject: [PATCH 10/38] styling changes --- website/frontend/styles/CleanAirPage.scss | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/website/frontend/styles/CleanAirPage.scss b/website/frontend/styles/CleanAirPage.scss index 4df0473083..43ea42804f 100644 --- a/website/frontend/styles/CleanAirPage.scss +++ b/website/frontend/styles/CleanAirPage.scss @@ -169,6 +169,10 @@ text-align: center; } + .splitSection-section.title-section{ + padding: 20px 0 10px 0; + } + .splitSection-section { display: grid; grid-template-columns: $gridColumn; @@ -909,13 +913,17 @@ .partner-img { width: 200px; height: auto; - padding: 50px; + padding: 20px 0; box-sizing: border-box; + max-width: 264px; + margin: 0 10px; img { width: 100%; - height: auto; + height: 100%; object-fit: contain; + max-width: 192px; + max-height: 110px; } } } @@ -1258,6 +1266,13 @@ display: none; } + .splitSection-section.title-section{ + margin-top: 0; + .backdrop-rev{ + grid-gap: 0; + } + } + .splitSection-section { width: 100%; padding: 40px 0; From acff8d0cb5d2bfcd7297c699dac9f748135b4529 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:47:24 +0300 Subject: [PATCH 11/38] add key for country mapper function --- website/frontend/src/components/Footer.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/website/frontend/src/components/Footer.js b/website/frontend/src/components/Footer.js index 5401fc66a0..464e283491 100644 --- a/website/frontend/src/components/Footer.js +++ b/website/frontend/src/components/Footer.js @@ -262,13 +262,15 @@ const Footer = () => {
    {t('footer.modal.country')}
    {/* The country list displayed here */} - {countries.map((country) => ( - + {countries.map((country, key) => ( +
    + +
    ))}
    From 93ff71e38d154f9e3681029dbe206adbfeacf326 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 09:47:42 +0300 Subject: [PATCH 12/38] event handling for partner logo --- website/frontend/src/pages/CleanAir/CleanAirPartners.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/CleanAirPartners.js b/website/frontend/src/pages/CleanAir/CleanAirPartners.js index 9e23da9ca4..2f37741be5 100644 --- a/website/frontend/src/pages/CleanAir/CleanAirPartners.js +++ b/website/frontend/src/pages/CleanAir/CleanAirPartners.js @@ -147,7 +147,7 @@ const CleanAirPartners = () => {
    {implementingPartners.slice(0, itemsToShow).map((networkPartner) => (
    0 ? { cursor: 'pointer' } : null} className="partner-img" key={networkPartner.id} onClick={onLogoClick(networkPartner)}> @@ -216,7 +216,7 @@ const CleanAirPartners = () => {
    {policyPartners.slice(0, itemsToShowPolicy).map((policyPartner) => (
    0 ? { cursor: 'pointer' } : null} className="partner-img" key={policyPartner.id} onClick={onLogoClick(policyPartner)}> @@ -283,7 +283,7 @@ const CleanAirPartners = () => {
    {privateSectorPartners.slice(0, itemsToShowPolicy).map((privatePartner) => (
    0 ? { cursor: 'pointer' } : null} className="partner-img" key={privatePartner.id} onClick={onLogoClick(privatePartner)}> @@ -353,7 +353,7 @@ const CleanAirPartners = () => {
    {supportPartners.slice(0, itemsToShowSupport).map((supportPartner) => (
    0 ? { cursor: 'pointer' } : null} className="partner-img" key={supportPartner.id} onClick={onLogoClick(supportPartner)}> From 3dbf0e27873088eb1c832c30c45345b8ff04ea54 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 10:03:05 +0300 Subject: [PATCH 13/38] event handling for location_link --- website/frontend/src/pages/CleanAir/EventDetails.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/website/frontend/src/pages/CleanAir/EventDetails.js b/website/frontend/src/pages/CleanAir/EventDetails.js index 4bb4018472..996d6b0c64 100644 --- a/website/frontend/src/pages/CleanAir/EventDetails.js +++ b/website/frontend/src/pages/CleanAir/EventDetails.js @@ -90,11 +90,9 @@ const EventDetails = () => { {event.location_name ? (
    - - - {event.location_name} - - + { + event.location_link !== null ? {event.location_name} : {event.location_name} + }
    ) : ( From 166530ee26236b4ed45fbacd8e4f8bc9280fd252 Mon Sep 17 00:00:00 2001 From: Ochieng Paul Date: Tue, 21 Nov 2023 11:56:41 +0300 Subject: [PATCH 14/38] removed extraction of last four items from the array --- platform/src/common/components/Customise/index.jsx | 4 +--- platform/src/common/components/Layout/index.jsx | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/src/common/components/Customise/index.jsx b/platform/src/common/components/Customise/index.jsx index 95828d4600..07b51cf4f5 100644 --- a/platform/src/common/components/Customise/index.jsx +++ b/platform/src/common/components/Customise/index.jsx @@ -21,8 +21,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { }); const selectedLocations = useSelector((state) => state.grids.selectedLocations) || []; const preferenceData = useSelector((state) => state.defaults.individual_preferences) || []; - const customisedLocations = - preferenceData.length > 0 ? preferenceData[0].selected_sites.slice(-4) : []; + const customisedLocations = preferenceData.length > 0 ? preferenceData[0].selected_sites : []; const id = useSelector((state) => state.login.userInfo._id); const chartData = useSelector((state) => state.chart); @@ -66,7 +65,6 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { setLoading(false); } else { toggleCustomise(); - // fetching user preferences after update dispatch(fetchUserPreferences(id)); dispatch(completeTask(2)); } diff --git a/platform/src/common/components/Layout/index.jsx b/platform/src/common/components/Layout/index.jsx index f3272805bf..ba395aef2e 100644 --- a/platform/src/common/components/Layout/index.jsx +++ b/platform/src/common/components/Layout/index.jsx @@ -53,7 +53,7 @@ const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorder ? selected_sites.map((site) => site['_id']) : chartData.chartSites; - await dispatch(setChartSites(chartSites.slice(-4))); + await dispatch(setChartSites(chartSites)); await dispatch( setChartDataRange({ startDate: startDate || chartData.chartDataRange.startDate, From 9f0d6d15eb79c371e792358b4d9d2f5e6249f9e6 Mon Sep 17 00:00:00 2001 From: Ochieng Paul Date: Tue, 21 Nov 2023 12:22:38 +0300 Subject: [PATCH 15/38] auto save of the user checklist items --- .../src/common/components/Layout/index.jsx | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/platform/src/common/components/Layout/index.jsx b/platform/src/common/components/Layout/index.jsx index ba395aef2e..6016f465d7 100644 --- a/platform/src/common/components/Layout/index.jsx +++ b/platform/src/common/components/Layout/index.jsx @@ -14,6 +14,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { fetchUserChecklists } from '@/lib/store/services/checklists/CheckData'; import { updateCards } from '@/lib/store/services/checklists/CheckList'; import Head from 'next/head'; +import { updateUserChecklists } from '@/lib/store/services/checklists/CheckData'; const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorderBottom }) => { // Constants @@ -27,6 +28,7 @@ const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorder const [collapsed, setCollapsed] = useState( () => JSON.parse(localStorage.getItem('collapsed')) || false, ); + const cardCheckList = useSelector((state) => state.cardChecklist.cards); // Fetching user preferences useEffect(() => { @@ -77,7 +79,7 @@ const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorder }, [userInfo, userPreferences, dispatch]); // Fetching user checklists - useEffect(() => { + const fetchData = () => { if (userInfo?._id && !localStorage.getItem('dataFetched')) { dispatch(fetchUserChecklists(userInfo._id)).then((action) => { if (fetchUserChecklists.fulfilled.match(action)) { @@ -85,15 +87,28 @@ const Layout = ({ pageTitle = 'AirQo Analytics', children, topbarTitle, noBorder if (payload && payload.length > 0) { const { items } = payload[0]; dispatch(updateCards(items)); - localStorage.setItem('dataFetched', 'true'); - } else { - localStorage.setItem('dataFetched', 'true'); - return; } + localStorage.setItem('dataFetched', 'true'); } }); } - }, [dispatch, userInfo]); + }; + + useEffect(fetchData, [dispatch, userInfo]); + + // update user checklists when ever the cardCheckList changes + const updateUserChecklist = () => { + if (userInfo?._id) { + dispatch( + updateUserChecklists({ + user_id: userInfo._id, + items: cardCheckList, + }), + ); + } + }; + + useEffect(updateUserChecklist, [dispatch, userInfo, cardCheckList]); useEffect(() => { localStorage.setItem('collapsed', collapsed); From f003bee8744518fdcdd2f0ca6d4e21cef4c6c407 Mon Sep 17 00:00:00 2001 From: Ochieng Paul Date: Tue, 21 Nov 2023 13:20:18 +0300 Subject: [PATCH 16/38] include logic for last and this quarter time period data --- .../components/Calendar/CustomCalendar.jsx | 46 +++++++------ .../Calendar/components/ShortCuts.jsx | 64 +++++++++++-------- 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/platform/src/common/components/Calendar/CustomCalendar.jsx b/platform/src/common/components/Calendar/CustomCalendar.jsx index 741609b6ea..c6784a6a0f 100644 --- a/platform/src/common/components/Calendar/CustomCalendar.jsx +++ b/platform/src/common/components/Calendar/CustomCalendar.jsx @@ -4,7 +4,16 @@ import ChevronDownIcon from '@/icons/Common/chevron_down.svg'; import { useSelector, useDispatch } from 'react-redux'; import { setChartDataRange } from '@/lib/store/services/charts/ChartSlice'; import Calendar from './Calendar'; -import { set } from 'date-fns'; +import { + differenceInDays, + isSameDay, + startOfMonth, + endOfMonth, + startOfQuarter, + endOfQuarter, + subMonths, + subDays, +} from 'date-fns'; const CustomCalendar = ({ initialStartDate, @@ -24,27 +33,15 @@ const CustomCalendar = ({ }); const handleValueChange = (newValue) => { - const computeDaysBetweenDates = (startDate, endDate) => { - const oneDay = 24 * 60 * 60 * 1000; - return Math.floor(Math.abs((startDate.getTime() - endDate.getTime()) / oneDay)); - }; - - const isSameDay = (date1, date2) => - date1.getDate() === date2.getDate() && - date1.getMonth() === date2.getMonth() && - date1.getFullYear() === date2.getFullYear(); - const handleDateChange = (newValue) => { const startDate = new Date(newValue.start); const endDate = new Date(newValue.end); const today = new Date(); - const yesterday = new Date(today); - yesterday.setDate(yesterday.getDate() - 1); - yesterday.setHours(0, 0, 0, 0); + const yesterday = subDays(today, 1); - const computedValue = computeDaysBetweenDates(startDate, endDate); + const computedValue = Math.abs(differenceInDays(startDate, endDate)); let label = `Last ${computedValue} days`; @@ -64,12 +61,9 @@ const CustomCalendar = ({ label = 'Last year'; } - // include also for This month and Last month - const thisMonthStart = new Date(today.getFullYear(), today.getMonth(), 1); - - const lastMonthStart = new Date(today.getFullYear(), today.getMonth() - 1, 1); - - const lastMonthEnd = new Date(today.getFullYear(), today.getMonth(), 0); + const thisMonthStart = startOfMonth(today); + const lastMonthStart = startOfMonth(subMonths(today, 1)); + const lastMonthEnd = endOfMonth(subMonths(today, 1)); if (isSameDay(startDate, thisMonthStart) && isSameDay(endDate, today)) { label = 'This month'; @@ -77,6 +71,16 @@ const CustomCalendar = ({ label = 'Last month'; } + const thisQuarterStart = startOfQuarter(today); + const lastQuarterStart = startOfQuarter(subMonths(today, 3)); + const lastQuarterEnd = endOfQuarter(subMonths(today, 3)); + + if (isSameDay(startDate, thisQuarterStart) && isSameDay(endDate, today)) { + label = 'This quarter'; + } else if (isSameDay(startDate, lastQuarterStart) && isSameDay(endDate, lastQuarterEnd)) { + label = 'Last quarter'; + } + dispatch(setChartDataRange({ startDate, endDate, label })); setValue(newValue); }; diff --git a/platform/src/common/components/Calendar/components/ShortCuts.jsx b/platform/src/common/components/Calendar/components/ShortCuts.jsx index 2411cb9aaf..bcf30bce89 100644 --- a/platform/src/common/components/Calendar/components/ShortCuts.jsx +++ b/platform/src/common/components/Calendar/components/ShortCuts.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { startOfDay, endOfDay, @@ -7,41 +7,49 @@ import { startOfYear, endOfMonth, endOfYear, + startOfQuarter, + endOfQuarter, + subQuarters, } from 'date-fns'; -const ShortCuts = ({ setSelectedRange }) => { - const timePeriods = [ - { label: 'Today', range: () => [startOfDay(new Date()), endOfDay(new Date())] }, - { - label: 'Yesterday', - range: () => [startOfDay(subDays(new Date(), 1)), endOfDay(subDays(new Date(), 1))], - }, - { - label: 'Last 7 days', - range: () => [startOfDay(subDays(new Date(), 7)), endOfDay(new Date())], - }, - { - label: 'Last 30 days', - range: () => [startOfDay(subDays(new Date(), 30)), endOfDay(new Date())], - }, - { - label: 'Last 90 days', - range: () => [startOfDay(subDays(new Date(), 90)), endOfDay(new Date())], - }, - { label: 'This month', range: () => [startOfMonth(new Date()), endOfMonth(new Date())] }, - { label: 'This year', range: () => [startOfYear(new Date()), endOfYear(new Date())] }, - { - label: 'Last year', - range: () => [startOfYear(subDays(new Date(), 365)), endOfYear(subDays(new Date(), 365))], - }, - ]; +const timePeriods = [ + { label: 'Today', range: () => [startOfDay(new Date()), endOfDay(new Date())] }, + { + label: 'Yesterday', + range: () => [startOfDay(subDays(new Date(), 1)), endOfDay(subDays(new Date(), 1))], + }, + { label: 'Last 7 days', range: () => [startOfDay(subDays(new Date(), 7)), endOfDay(new Date())] }, + { + label: 'Last 30 days', + range: () => [startOfDay(subDays(new Date(), 30)), endOfDay(new Date())], + }, + { + label: 'Last 90 days', + range: () => [startOfDay(subDays(new Date(), 90)), endOfDay(new Date())], + }, + { label: 'This month', range: () => [startOfMonth(new Date()), endOfMonth(new Date())] }, + { label: 'This year', range: () => [startOfYear(new Date()), endOfYear(new Date())] }, + { + label: 'Last year', + range: () => [startOfYear(subDays(new Date(), 365)), endOfYear(subDays(new Date(), 365))], + }, + { label: 'This quarter', range: () => [startOfQuarter(new Date()), endOfQuarter(new Date())] }, + { + label: 'Last quarter', + range: () => [ + startOfQuarter(subQuarters(new Date(), 1)), + endOfQuarter(subQuarters(new Date(), 1)), + ], + }, +]; +const ShortCuts = ({ setSelectedRange }) => { const handleShortcutClick = (range) => { setSelectedRange({ start: range()[0], end: range()[1] }); }; return ( -
    +
      {timePeriods.map((period) => (
    • From 388fd04275ebe1d6ce35dbe1b18d3c63c1e2baea Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:42:45 +0300 Subject: [PATCH 17/38] saves active organisation to preferences api - formats organisation names in dropdown to uppercase and removes underscores --- .../components/Dropdowns/CustomDropdown.jsx | 5 +- .../Dropdowns/OrganizationDropdown.jsx | 76 ++++++++++++++++--- platform/src/pages/account/login/index.jsx | 4 +- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/platform/src/common/components/Dropdowns/CustomDropdown.jsx b/platform/src/common/components/Dropdowns/CustomDropdown.jsx index e75358376c..3b31c3c209 100644 --- a/platform/src/common/components/Dropdowns/CustomDropdown.jsx +++ b/platform/src/common/components/Dropdowns/CustomDropdown.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; -const CustomDropdown = ({ trigger, children, className, id }) => { +const CustomDropdown = ({ trigger, children, className, id, dropdownWidth = '200px' }) => { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); @@ -25,7 +25,8 @@ const CustomDropdown = ({ trigger, children, className, id }) => { {React.cloneElement(trigger, { onClick: handleDropdown })} {isOpen && (
      + className={`absolute w-[${dropdownWidth}] mt-2 bg-white border border-gray-200 divide-y divide-gray-100 rounded-md shadow-lg z-50 ${className}`} + >
      {children}
      )} diff --git a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx index 05279e8345..da416810de 100644 --- a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx +++ b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx @@ -2,6 +2,9 @@ import { useEffect, useState } from 'react'; import CustomDropdown from './CustomDropdown'; import CheckIcon from '@/icons/tickIcon'; import ChevronDownIcon from '@/icons/Common/chevron_down.svg'; +import { useDispatch } from 'react-redux'; +import { updateUserPreferences } from '@/lib/store/services/account/UserDefaultsSlice'; +import Spinner from '@/components/Spinner'; const splitNameIntoList = (fullName) => { if (fullName && fullName.length > 0) { @@ -11,17 +14,48 @@ const splitNameIntoList = (fullName) => { return; }; +export const formatString = (string) => { + return string + .replace(/_/g, ' ') + .replace(/\w\S*/g, (txt) => { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }) + .replace('Id', 'ID'); +}; + const OrganizationDropdown = () => { + const dispatch = useDispatch(); const [activeGroup, setActiveGroup] = useState({}); const [userGroups, setUserGroups] = useState([]); + const [loading, setLoading] = useState(false); useEffect(() => { const storedActiveGroup = localStorage.getItem('activeGroup'); - const storedUserGroups = localStorage.getItem('loggedUser'); - const userGroups = JSON.parse(storedUserGroups)?.groups; + const storedUser = localStorage.getItem('loggedUser'); + const userGroups = JSON.parse(storedUser)?.groups; + const userId = JSON.parse(storedUser)?._id; + + const handleUpdatePreferences = async () => { + setLoading(true); + const data = { + user_id: userId, + group_id: JSON.parse(storedActiveGroup)?._id, + }; + + try { + const response = await dispatch(updateUserPreferences(data)); + if (response.payload.success) { + setActiveGroup(JSON.parse(storedActiveGroup)); + } + } catch (error) { + throw error; + } finally { + setLoading(false); + } + }; if (storedActiveGroup !== null) { - setActiveGroup(JSON.parse(storedActiveGroup)); + handleUpdatePreferences(); } if (userGroups) { @@ -29,9 +63,26 @@ const OrganizationDropdown = () => { } }, []); - const handleDropdownSelect = (option) => { - setActiveGroup(option); - localStorage.setItem('activeGroup', JSON.stringify(option)); + const handleDropdownSelect = async (option) => { + setLoading(true); + const storedUser = localStorage.getItem('loggedUser'); + const userId = JSON.parse(storedUser)?._id; + const data = { + user_id: userId, + group_id: option._id, + }; + + try { + const response = await dispatch(updateUserPreferences(data)); + if (response.payload.success) { + setActiveGroup(option); + localStorage.setItem('activeGroup', JSON.stringify(option)); + } + } catch (error) { + throw error; + } finally { + setLoading(false); + } }; return ( @@ -70,10 +121,10 @@ const OrganizationDropdown = () => { } id='options' + dropdownWidth='224px' dropStyle={{ top: '41px', zIndex: 999, - width: '224px', maxHeight: '320px', overflowY: 'scroll', overflowX: 'hidden', @@ -82,7 +133,7 @@ const OrganizationDropdown = () => { > {userGroups.map((format) => ( handleDropdownSelect(format)} className={`w-full h-11 px-3.5 py-2.5 justify-between items-center inline-flex ${ @@ -102,8 +153,13 @@ const OrganizationDropdown = () => { : splitNameIntoList(format?.grp_title)[0][0]}
    -
    - {format.grp_title} +
    + {format && format.grp_title && format.grp_title.length > 24 + ? formatString(format.grp_title.slice(0, 24)) + '...' + : formatString(format.grp_title)}
    {activeGroup && activeGroup?.grp_title === format?.grp_title && ( diff --git a/platform/src/pages/account/login/index.jsx b/platform/src/pages/account/login/index.jsx index fbb681c680..f339c51085 100644 --- a/platform/src/pages/account/login/index.jsx +++ b/platform/src/pages/account/login/index.jsx @@ -21,6 +21,7 @@ const UserLogin = () => { const postData = useSelector((state) => state.login); const [loading, setLoading] = useState(false); const [passwordType, setPasswordType] = useState('password'); + const preferences = useSelector((state) => state.defaults.individual_preferences); const handleLogin = async (e) => { e.preventDefault(); @@ -137,7 +138,8 @@ const UserLogin = () => {
    From ac5399de0b0b756b0d3f7746a7f65036abca9c3c Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:53:06 +0300 Subject: [PATCH 18/38] modified logic for set active organisation on login --- .../Dropdowns/OrganizationDropdown.jsx | 14 +++++++++++--- platform/src/pages/account/login/index.jsx | 19 ++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx index da416810de..2801dea848 100644 --- a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx +++ b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import CustomDropdown from './CustomDropdown'; import CheckIcon from '@/icons/tickIcon'; import ChevronDownIcon from '@/icons/Common/chevron_down.svg'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { updateUserPreferences } from '@/lib/store/services/account/UserDefaultsSlice'; import Spinner from '@/components/Spinner'; @@ -28,6 +28,7 @@ const OrganizationDropdown = () => { const [activeGroup, setActiveGroup] = useState({}); const [userGroups, setUserGroups] = useState([]); const [loading, setLoading] = useState(false); + const preferences = useSelector((state) => state.defaults.individual_preferences); useEffect(() => { const storedActiveGroup = localStorage.getItem('activeGroup'); @@ -54,8 +55,15 @@ const OrganizationDropdown = () => { } }; - if (storedActiveGroup !== null) { + if ( + storedActiveGroup !== null && + preferences && + preferences[0] && + preferences[0].group_id === '' + ) { handleUpdatePreferences(); + } else { + setActiveGroup(JSON.parse(storedActiveGroup)); } if (userGroups) { @@ -136,7 +144,7 @@ const OrganizationDropdown = () => { key={format._id} href='#' onClick={() => handleDropdownSelect(format)} - className={`w-full h-11 px-3.5 py-2.5 justify-between items-center inline-flex ${ + className={`w-56 h-11 px-3.5 py-2.5 justify-between items-center inline-flex ${ activeGroup && activeGroup?.grp_title === format?.grp_title && 'bg-secondary-neutral-light-50' diff --git a/platform/src/pages/account/login/index.jsx b/platform/src/pages/account/login/index.jsx index f339c51085..9dd40e679b 100644 --- a/platform/src/pages/account/login/index.jsx +++ b/platform/src/pages/account/login/index.jsx @@ -46,11 +46,20 @@ const UserLogin = () => { setLoading(false); return; } - // find airqo group in the users groups and set it as the active group - const airqoGroup = response.users[0].groups.find( - (group) => group.grp_title === 'airqo', - ); - localStorage.setItem('activeGroup', JSON.stringify(airqoGroup)); + + // check if user has a saved organisation + if (preferences && preferences[0] && preferences[0].group_id) { + const activeGroup = response.users[0].groups.find( + (group) => group._id === preferences[0].group_id, + ); + localStorage.setItem('activeGroup', JSON.stringify(activeGroup)); + } else { + const airqoGroup = response.users[0].groups.find( + (group) => group.grp_title === 'airqo', + ); + localStorage.setItem('activeGroup', JSON.stringify(airqoGroup)); + } + dispatch(setUserInfo(response.users[0])); dispatch(setSuccess(true)); setLoading(false); From 5783a750a29a9a54ad2cdb6b0490ca380906295b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:54:15 +0300 Subject: [PATCH 19/38] Update next platform staging image tag to stage-750bcb26-1700563894 --- k8s/platform/values-stage.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/platform/values-stage.yaml b/k8s/platform/values-stage.yaml index 528d436536..b771f80870 100644 --- a/k8s/platform/values-stage.yaml +++ b/k8s/platform/values-stage.yaml @@ -2,7 +2,7 @@ replicaCount: 1 image: repository: eu.gcr.io/airqo-250220/airqo-stage-next-platform pullPolicy: Always - tag: stage-7542a4b5-1700216129 + tag: stage-750bcb26-1700563894 imagePullSecrets: [] nameOverride: '' fullnameOverride: '' From 28c7504104b2ba515c6169961702fc31c489bb68 Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 13:55:51 +0300 Subject: [PATCH 20/38] patch user preferences --- platform/src/core/apis/Account.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/platform/src/core/apis/Account.js b/platform/src/core/apis/Account.js index 0155c833c1..f9540f2f17 100644 --- a/platform/src/core/apis/Account.js +++ b/platform/src/core/apis/Account.js @@ -149,7 +149,7 @@ export const updateUserPreferencesApi = async (data) => { } } -// Get Individual user preferences +// Get Individual User preferences export const getUserPreferencesApi = async (identifier) => { try { const response = await createAxiosInstance().get(`${USER_PREFERENCES_URL}/${identifier}`); @@ -160,6 +160,18 @@ export const getUserPreferencesApi = async (identifier) => { } } +// Patch/Replace User Preferences +export const patchUserPreferencesApi = async (data) => { + try { + const response = await createAxiosInstance().patch(`${USER_PREFERENCES_URL}/replace`, data); + return response.data; + } + catch (error) { + throw error; + } +} + +// User Defaults export const getUserDefaults = async () => { return await createAxiosInstance() .get(USER_DEFAULTS_URL) @@ -176,6 +188,7 @@ export const updateUserDefaults = async (defaultsId, defaults) => { .then((response) => response.data); }; +// User Checklist export const getUserChecklists = async (userID) => { return await createAxiosInstance() .get(`${USER_CHECKLISTS_URL}/${userID}`) @@ -188,6 +201,7 @@ export const upsertUserChecklists = async (checklist) => { .then((response) => response.data); }; +// Group Details export const getGroupDetailsApi = async (groupID) => { return await createAxiosInstance() .get(`${GROUPS_URL}/${groupID}`) From 17e2902b436eb6b8d61b26c82f9dd38fc2cfa82e Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 13:56:04 +0300 Subject: [PATCH 21/38] patch user preferences redux --- .../services/account/UserDefaultsSlice.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/platform/src/lib/store/services/account/UserDefaultsSlice.js b/platform/src/lib/store/services/account/UserDefaultsSlice.js index b9a1fa3a12..25f0ef5949 100644 --- a/platform/src/lib/store/services/account/UserDefaultsSlice.js +++ b/platform/src/lib/store/services/account/UserDefaultsSlice.js @@ -1,4 +1,4 @@ -import { getUserPreferencesApi, postUserDefaultsApi, postUserPreferencesApi, updateUserDefaultsApi, updateUserPreferencesApi } from '@/core/apis/Account'; +import { getUserPreferencesApi, patchUserPreferencesApi, postUserDefaultsApi, postUserPreferencesApi, updateUserDefaultsApi, updateUserPreferencesApi } from '@/core/apis/Account'; import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; const initialState = { @@ -47,6 +47,18 @@ export const getIndividualUserPreferences = createAsyncThunk('/get/individual/pr } }) +export const replaceUserPreferences = createAsyncThunk('/replace/individual/preference', async (data, { rejectWithValue }) => { + try { + const response = await patchUserPreferencesApi(data); + return response + } catch (error) { + if (!error.response) { + throw error + } + return rejectWithValue(error.response.data); + } +}) + export const defaultsSlice = createSlice({ name: 'defaults', initialState, @@ -90,6 +102,10 @@ export const defaultsSlice = createSlice({ state.errors = action.payload; state.success = false; }) + .addCase(replaceUserPreferences.rejected, (state, action) => { + state.errors = action.payload; + state.success = false; + }) } }) From 387eb8008c108d8d2f0d4e0bc35ca8830d9fbcb0 Mon Sep 17 00:00:00 2001 From: Belinda Marion Kobusingye <46527380+Codebmk@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:57:32 +0300 Subject: [PATCH 22/38] add spinner to selected organisations --- .../common/components/Dropdowns/OrganizationDropdown.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx index 2801dea848..364e136c04 100644 --- a/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx +++ b/platform/src/common/components/Dropdowns/OrganizationDropdown.jsx @@ -28,6 +28,7 @@ const OrganizationDropdown = () => { const [activeGroup, setActiveGroup] = useState({}); const [userGroups, setUserGroups] = useState([]); const [loading, setLoading] = useState(false); + const [selectedGroup, setSelectedGroup] = useState({}); const preferences = useSelector((state) => state.defaults.individual_preferences); useEffect(() => { @@ -79,6 +80,7 @@ const OrganizationDropdown = () => { user_id: userId, group_id: option._id, }; + setSelectedGroup(option); try { const response = await dispatch(updateUserPreferences(data)); @@ -90,6 +92,7 @@ const OrganizationDropdown = () => { throw error; } finally { setLoading(false); + setSelectedGroup({}); } }; @@ -173,6 +176,11 @@ const OrganizationDropdown = () => { {activeGroup && activeGroup?.grp_title === format?.grp_title && ( )} + {loading && selectedGroup._id === format._id && ( + + + + )} ))} From 50831cb745d1dfdafe1541d4bf41937cc5c2cd2e Mon Sep 17 00:00:00 2001 From: FaithDaka Date: Tue, 21 Nov 2023 13:58:01 +0300 Subject: [PATCH 23/38] use patch instead of update for user preferences --- platform/src/common/components/Customise/index.jsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/platform/src/common/components/Customise/index.jsx b/platform/src/common/components/Customise/index.jsx index 01a33083cb..cd8fda6517 100644 --- a/platform/src/common/components/Customise/index.jsx +++ b/platform/src/common/components/Customise/index.jsx @@ -4,7 +4,7 @@ import LocationsContentComponent from './LocationsContentComponent'; import { useDispatch, useSelector } from 'react-redux'; import Spinner from '@/components/Spinner'; import { - updateUserPreferences, + replaceUserPreferences, getIndividualUserPreferences, } from '@/lib/store/services/account/UserDefaultsSlice'; import Toast from '@/components/Toast'; @@ -54,18 +54,17 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { }, }; try { - const response = await dispatch(updateUserPreferences(data)); - + const response = await dispatch(replaceUserPreferences(data)); if (!response.payload.success) { setCreationErrors({ state: true, message: response.payload.message, }); - setLoading(false); } else { toggleCustomise(); // fetching user preferences after update + dispatch(getIndividualUserPreferences(id)); dispatch(fetchUserPreferences(id)); } } catch (error) { @@ -77,7 +76,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { useEffect(() => { dispatch(getIndividualUserPreferences(id)); - }, [preferenceData]); + }, []); return (
    @@ -85,7 +84,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { )}

    Customise

    @@ -123,7 +122,7 @@ const CustomiseLocationsComponent = ({ toggleCustomise }) => { )} {/* TODO: Pollutant component and post selection to user defaults */}
    -
    +