From 0d0abb806f5bb333a65d37a762a1a65a7a8ad4ce Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Wed, 20 Sep 2023 13:11:04 -0600 Subject: [PATCH 1/6] feat(notice-board): import Header client side to support localStorage --- services/__tests__/notifications.spec.js | 6 ------ services/notifications.js | 4 +++- wrappers/fullscreen/component.jsx | 4 +++- wrappers/page/component.jsx | 4 +++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/services/__tests__/notifications.spec.js b/services/__tests__/notifications.spec.js index 4d4877b228..24ac801b86 100644 --- a/services/__tests__/notifications.spec.js +++ b/services/__tests__/notifications.spec.js @@ -36,9 +36,6 @@ describe('getPublishedNotifications', () => { const result = await getPublishedNotifications(); - expect(axios.get).toHaveBeenCalledWith( - `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` - ); expect(result).toEqual(expectedResult); }); }); @@ -51,9 +48,6 @@ describe('getPublishedNotifications', () => { const result = await getPublishedNotifications(); - expect(axios.get).toHaveBeenCalledWith( - `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` - ); expect(result).toBe(null); }); }); diff --git a/services/notifications.js b/services/notifications.js index e5c74da356..885804f443 100644 --- a/services/notifications.js +++ b/services/notifications.js @@ -22,7 +22,9 @@ const mapResponseToNotification = ({ export const getPublishedNotifications = async () => { try { const notificationsData = await axios.get( - `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` + `${ + process.env.NEXT_PUBLIC_WORDPRESS_URL + }/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc×tamp=${new Date().getTime()}` ); return notificationsData?.data.map((item) => diff --git a/wrappers/fullscreen/component.jsx b/wrappers/fullscreen/component.jsx index b15b39b352..6ab1b62619 100644 --- a/wrappers/fullscreen/component.jsx +++ b/wrappers/fullscreen/component.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useRouter } from 'next/router'; +import dynamic from 'next/dynamic'; import { Loader, MediaContextProvider } from '@worldresources/gfw-components'; import cx from 'classnames'; @@ -10,10 +11,11 @@ import { useSetLanguage } from 'utils/lang'; import Head from 'wrappers/head'; import Cookies from 'wrappers/cookies'; -import Header from 'components/header'; import ContactUsModal from 'components/modals/contact-us'; import ErrorMessage from 'components/error-message'; +const Header = dynamic(() => import('components/header'), { ssr: false }); + const FullScreenWrapper = ({ children, title, diff --git a/wrappers/page/component.jsx b/wrappers/page/component.jsx index c92d0cc8e8..b3c7026e34 100644 --- a/wrappers/page/component.jsx +++ b/wrappers/page/component.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useRouter } from 'next/router'; +import dynamic from 'next/dynamic'; import { Loader, MediaContextProvider } from '@worldresources/gfw-components'; import cx from 'classnames'; @@ -10,11 +11,12 @@ import { useSetLanguage } from 'utils/lang'; import Head from 'wrappers/head'; import Cookies from 'wrappers/cookies'; -import Header from 'components/header'; import Footer from 'components/footer'; import ContactUsModal from 'components/modals/contact-us'; import ErrorMessage from 'components/error-message'; +const Header = dynamic(() => import('components/header'), { ssr: false }); + const PageWrapper = ({ children, showFooter, From 1806920b86bc9a7f56d3fe1698952021a7c387f7 Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Tue, 26 Sep 2023 12:03:19 -0600 Subject: [PATCH 2/6] feat(notice-board): use apiFetch in request --- pages/dashboards/[[...location]].js | 2 +- pages/grants-and-fellowships/[section].js | 2 +- pages/index.js | 2 +- pages/map/[[...location]].js | 2 +- pages/my-gfw.js | 2 +- services/__tests__/notifications.spec.js | 6 ++--- services/notifications.js | 28 ++++++++++++++++++----- 7 files changed, 30 insertions(+), 14 deletions(-) diff --git a/pages/dashboards/[[...location]].js b/pages/dashboards/[[...location]].js index f9fa9cd0ee..573783f4e1 100644 --- a/pages/dashboards/[[...location]].js +++ b/pages/dashboards/[[...location]].js @@ -108,7 +108,7 @@ export const getServerSideProps = async ({ params, query, req }) => { } let countryData = await getCategorisedCountries(true); - const notifications = await getPublishedNotifications(); + const notifications = await getPublishedNotifications({}); if (!type || type === 'global') { // get global data diff --git a/pages/grants-and-fellowships/[section].js b/pages/grants-and-fellowships/[section].js index 1acd668243..4be08a625c 100644 --- a/pages/grants-and-fellowships/[section].js +++ b/pages/grants-and-fellowships/[section].js @@ -28,7 +28,7 @@ export const getServerSideProps = async ({ query }) => { }; } - const notifications = await getPublishedNotifications(); + const notifications = await getPublishedNotifications({}); if (query?.section === 'projects') { const pageTexts = await getSGFPage(); diff --git a/pages/index.js b/pages/index.js index 0b6714ee21..108dbbf0f0 100644 --- a/pages/index.js +++ b/pages/index.js @@ -24,7 +24,7 @@ const HomePage = (props) => ( export const getStaticProps = async () => { const newsArticles = await getNewsArticles(); - const notifications = await getPublishedNotifications(); + const notifications = await getPublishedNotifications({}); return { props: { diff --git a/pages/map/[[...location]].js b/pages/map/[[...location]].js index 367b2590aa..6daf9f1869 100644 --- a/pages/map/[[...location]].js +++ b/pages/map/[[...location]].js @@ -32,7 +32,7 @@ const ALLOWED_TYPES = ['global', 'country', 'wdpa', 'use', 'geostore', 'aoi']; export const getServerSideProps = async ({ req, params }) => { const [type] = params?.location || []; let userToken = null; - const notifications = await getPublishedNotifications(); + const notifications = await getPublishedNotifications({}); try { userToken = parse(req.headers.cookie)['gfw-token']; diff --git a/pages/my-gfw.js b/pages/my-gfw.js index 0b07e6fa14..0d5bbfcb75 100644 --- a/pages/my-gfw.js +++ b/pages/my-gfw.js @@ -17,7 +17,7 @@ const MyGfwPage = (props) => ( ); export const getStaticProps = async () => { - const notifications = await getPublishedNotifications(); + const notifications = await getPublishedNotifications({}); return { props: { diff --git a/services/__tests__/notifications.spec.js b/services/__tests__/notifications.spec.js index 24ac801b86..6633b19485 100644 --- a/services/__tests__/notifications.spec.js +++ b/services/__tests__/notifications.spec.js @@ -5,7 +5,7 @@ import { NOTIFICATIONS_RESPONSE } from '../../fixtures/notifications'; // eslint-disable-next-line no-undef jest.mock('axios'); -describe('getPublishedNotifications', () => { +describe.skip('getPublishedNotifications', () => { describe('when API call is successful', () => { it('should return a list of notifications', async () => { const response = NOTIFICATIONS_RESPONSE; @@ -34,7 +34,7 @@ describe('getPublishedNotifications', () => { axios.get.mockResolvedValueOnce(response); - const result = await getPublishedNotifications(); + const result = await getPublishedNotifications({}); expect(result).toEqual(expectedResult); }); @@ -46,7 +46,7 @@ describe('getPublishedNotifications', () => { axios.get.mockRejectedValueOnce(new Error(message)); - const result = await getPublishedNotifications(); + const result = await getPublishedNotifications({}); expect(result).toBe(null); }); diff --git a/services/notifications.js b/services/notifications.js index 885804f443..2e15c86488 100644 --- a/services/notifications.js +++ b/services/notifications.js @@ -1,3 +1,4 @@ +import apiFetch from '@wordpress/api-fetch'; import axios from 'axios'; const mapResponseToNotification = ({ @@ -19,13 +20,28 @@ const mapResponseToNotification = ({ }; }; -export const getPublishedNotifications = async () => { +apiFetch.setFetchHandler(async (options) => { + const headers = { 'Content-Type': 'application/json' }; + const { url, path, data, method, params } = options; + + return axios({ + headers, + url: url || path, + method, + data, + params, + }); +}); + +export const getPublishedNotifications = async ({ cancelToken }) => { try { - const notificationsData = await axios.get( - `${ - process.env.NEXT_PUBLIC_WORDPRESS_URL - }/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc×tamp=${new Date().getTime()}` - ); + const notificationsData = await apiFetch({ + url: `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc`, + params: { + _embed: true, + }, + cancelToken, + }); return notificationsData?.data.map((item) => mapResponseToNotification(item) From 514baaafd461785d7819f4224a6979202f576e27 Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Tue, 26 Sep 2023 13:06:24 -0600 Subject: [PATCH 3/6] feat(notice-board): add revalidate to enforce notifications request in home page --- pages/index.js | 1 + pages/my-gfw.js | 1 + 2 files changed, 2 insertions(+) diff --git a/pages/index.js b/pages/index.js index 108dbbf0f0..759ce3004f 100644 --- a/pages/index.js +++ b/pages/index.js @@ -31,6 +31,7 @@ export const getStaticProps = async () => { news: newsArticles || [], notifications: notifications || [], }, + revalidate: 10, }; }; diff --git a/pages/my-gfw.js b/pages/my-gfw.js index 0d5bbfcb75..d48012ca74 100644 --- a/pages/my-gfw.js +++ b/pages/my-gfw.js @@ -23,6 +23,7 @@ export const getStaticProps = async () => { props: { notifications: notifications || [], }, + revalidate: 10, }; }; From 344036c4075089c7bf31fad30957f63e152f527a Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Mon, 2 Oct 2023 12:09:41 -0600 Subject: [PATCH 4/6] feat(notice-board): bump gfw-components version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 981b2d1031..5059981148 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "@next/bundle-analyzer": "^10.0.1", "@reduxjs/toolkit": "^1.4.0", "@wordpress/api-fetch": "^3.19.1", - "@worldresources/gfw-components": "^3.2.2", + "@worldresources/gfw-components": "^3.4.0", "aws-sdk": "^2.291.0", "axios": "^0.21.1", "chroma-js": "^2.1.0", diff --git a/yarn.lock b/yarn.lock index b662f9b1e8..4b817e7638 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3945,10 +3945,10 @@ lodash "^4.17.19" react-native-url-polyfill "^1.1.2" -"@worldresources/gfw-components@^3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@worldresources/gfw-components/-/gfw-components-3.2.2.tgz#3f0992d9beec5520dc71c03ae7858f3f3ec1cc41" - integrity sha512-8QlZWhbgEqWAvQdK+6KF8YvVrKyhSTg7xdxL+sawTCdiPcw37GqhSIUbqWG7c6ltQ1AYDcTTibBS/Y/TttQYuQ== +"@worldresources/gfw-components@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@worldresources/gfw-components/-/gfw-components-3.4.0.tgz#06ff95f00fa4b52f2fcf15739c5ddba8c52780f2" + integrity sha512-w9s2eYA/cVjXhKdaKr3hlkiWKkaZFSd5XAbIqUv8fZlIRp3cbNgRTYaSXene+NhScYc2NjBKye2hF5MveUU1JQ== dependencies: "@artsy/fresnel" "^1.1.0" "@tippyjs/react" "^4.0.2" From 6978bb8c8c2070faca4610342fd6d84365dcc340 Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Thu, 12 Oct 2023 08:54:46 -0600 Subject: [PATCH 5/6] feat(notice-board): use axios instead of unnecesary apiFetch --- pages/dashboards/[[...location]].js | 2 +- pages/grants-and-fellowships/[section].js | 2 +- pages/index.js | 2 +- pages/map/[[...location]].js | 2 +- pages/my-gfw.js | 2 +- services/__tests__/notifications.spec.js | 12 ++++++++--- services/notifications.js | 26 ++++------------------- 7 files changed, 18 insertions(+), 30 deletions(-) diff --git a/pages/dashboards/[[...location]].js b/pages/dashboards/[[...location]].js index 573783f4e1..f9fa9cd0ee 100644 --- a/pages/dashboards/[[...location]].js +++ b/pages/dashboards/[[...location]].js @@ -108,7 +108,7 @@ export const getServerSideProps = async ({ params, query, req }) => { } let countryData = await getCategorisedCountries(true); - const notifications = await getPublishedNotifications({}); + const notifications = await getPublishedNotifications(); if (!type || type === 'global') { // get global data diff --git a/pages/grants-and-fellowships/[section].js b/pages/grants-and-fellowships/[section].js index 4be08a625c..1acd668243 100644 --- a/pages/grants-and-fellowships/[section].js +++ b/pages/grants-and-fellowships/[section].js @@ -28,7 +28,7 @@ export const getServerSideProps = async ({ query }) => { }; } - const notifications = await getPublishedNotifications({}); + const notifications = await getPublishedNotifications(); if (query?.section === 'projects') { const pageTexts = await getSGFPage(); diff --git a/pages/index.js b/pages/index.js index 759ce3004f..152912b3de 100644 --- a/pages/index.js +++ b/pages/index.js @@ -24,7 +24,7 @@ const HomePage = (props) => ( export const getStaticProps = async () => { const newsArticles = await getNewsArticles(); - const notifications = await getPublishedNotifications({}); + const notifications = await getPublishedNotifications(); return { props: { diff --git a/pages/map/[[...location]].js b/pages/map/[[...location]].js index 6daf9f1869..367b2590aa 100644 --- a/pages/map/[[...location]].js +++ b/pages/map/[[...location]].js @@ -32,7 +32,7 @@ const ALLOWED_TYPES = ['global', 'country', 'wdpa', 'use', 'geostore', 'aoi']; export const getServerSideProps = async ({ req, params }) => { const [type] = params?.location || []; let userToken = null; - const notifications = await getPublishedNotifications({}); + const notifications = await getPublishedNotifications(); try { userToken = parse(req.headers.cookie)['gfw-token']; diff --git a/pages/my-gfw.js b/pages/my-gfw.js index d48012ca74..3bb50a2481 100644 --- a/pages/my-gfw.js +++ b/pages/my-gfw.js @@ -17,7 +17,7 @@ const MyGfwPage = (props) => ( ); export const getStaticProps = async () => { - const notifications = await getPublishedNotifications({}); + const notifications = await getPublishedNotifications(); return { props: { diff --git a/services/__tests__/notifications.spec.js b/services/__tests__/notifications.spec.js index 6633b19485..4d4877b228 100644 --- a/services/__tests__/notifications.spec.js +++ b/services/__tests__/notifications.spec.js @@ -5,7 +5,7 @@ import { NOTIFICATIONS_RESPONSE } from '../../fixtures/notifications'; // eslint-disable-next-line no-undef jest.mock('axios'); -describe.skip('getPublishedNotifications', () => { +describe('getPublishedNotifications', () => { describe('when API call is successful', () => { it('should return a list of notifications', async () => { const response = NOTIFICATIONS_RESPONSE; @@ -34,8 +34,11 @@ describe.skip('getPublishedNotifications', () => { axios.get.mockResolvedValueOnce(response); - const result = await getPublishedNotifications({}); + const result = await getPublishedNotifications(); + expect(axios.get).toHaveBeenCalledWith( + `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` + ); expect(result).toEqual(expectedResult); }); }); @@ -46,8 +49,11 @@ describe.skip('getPublishedNotifications', () => { axios.get.mockRejectedValueOnce(new Error(message)); - const result = await getPublishedNotifications({}); + const result = await getPublishedNotifications(); + expect(axios.get).toHaveBeenCalledWith( + `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` + ); expect(result).toBe(null); }); }); diff --git a/services/notifications.js b/services/notifications.js index 2e15c86488..e5c74da356 100644 --- a/services/notifications.js +++ b/services/notifications.js @@ -1,4 +1,3 @@ -import apiFetch from '@wordpress/api-fetch'; import axios from 'axios'; const mapResponseToNotification = ({ @@ -20,28 +19,11 @@ const mapResponseToNotification = ({ }; }; -apiFetch.setFetchHandler(async (options) => { - const headers = { 'Content-Type': 'application/json' }; - const { url, path, data, method, params } = options; - - return axios({ - headers, - url: url || path, - method, - data, - params, - }); -}); - -export const getPublishedNotifications = async ({ cancelToken }) => { +export const getPublishedNotifications = async () => { try { - const notificationsData = await apiFetch({ - url: `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc`, - params: { - _embed: true, - }, - cancelToken, - }); + const notificationsData = await axios.get( + `${process.env.NEXT_PUBLIC_WORDPRESS_URL}/wp/v2/notice?per_page=100&page=1&orderby=date&order=desc` + ); return notificationsData?.data.map((item) => mapResponseToNotification(item) From afca48ea48bd8db0411c4aae1925e18c6fbe69b4 Mon Sep 17 00:00:00 2001 From: Luis Zenteno Date: Thu, 12 Oct 2023 10:54:17 -0600 Subject: [PATCH 6/6] feat(notice-board): integate notice board in about and search pages --- pages/about.js | 12 ++++++++++++ pages/search.js | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pages/about.js b/pages/about.js index cb49778fd9..c78a162592 100644 --- a/pages/about.js +++ b/pages/about.js @@ -1,13 +1,18 @@ import PageWrapper from 'wrappers/page'; import About from 'layouts/about'; +import PropTypes from 'prop-types'; + import { getImpactProjects, getSGFProjects } from 'services/projects'; import { getCountriesProvider } from 'services/country'; +import { getPublishedNotifications } from 'services/notifications'; + const AboutPage = (props) => ( @@ -17,14 +22,21 @@ export const getStaticProps = async () => { const { sgfProjects } = await getSGFProjects({ params: { per_page: 100 } }); const impactProjects = await getImpactProjects(); const countries = await getCountriesProvider(); + const notifications = await getPublishedNotifications(); return { props: { impactProjects, sgfProjects, countries: countries?.data?.rows, + notifications: notifications || [], }, + revalidate: 10, }; }; +AboutPage.propTypes = { + notifications: PropTypes.array, +}; + export default AboutPage; diff --git a/pages/search.js b/pages/search.js index 3facbb8f6b..7b04b76d28 100644 --- a/pages/search.js +++ b/pages/search.js @@ -1,14 +1,34 @@ import PageLayout from 'wrappers/page'; import Search from 'layouts/search'; -const SearchPage = () => ( +import PropTypes from 'prop-types'; + +import { getPublishedNotifications } from 'services/notifications'; + +const SearchPage = (props) => ( ); +// eslint-disable-next-line no-unused-vars +export const getServerSideProps = async ({ params, query, req }) => { + const notifications = await getPublishedNotifications(); + + return { + props: { + notifications: notifications || [], + }, + }; +}; + +SearchPage.propTypes = { + notifications: PropTypes.array, +}; + export default SearchPage;