diff --git a/.env.development b/.env.development index a53025ff..b3cae8f4 100644 --- a/.env.development +++ b/.env.development @@ -2,8 +2,8 @@ # To override locally, make a copy called `.env.development.local` # Refer: https://nextjs.org/docs/basic-features/environment-variables -NEXT_PUBLIC_OONI_API=https://backend-hel.ooni.org -NEXT_PUBLIC_USER_FEEDBACK_API=https://backend-hel.ooni.org +NEXT_PUBLIC_OONI_API=https://api.ooni.org +NEXT_PUBLIC_USER_FEEDBACK_API=https://api.dev.ooni.io NEXT_PUBLIC_EXPLORER_URL=http://localhost:3100 RUN_GIT_COMMIT_SHA_SHORT=yarn --silent git:getCommitSHA:short diff --git a/.env.test b/.env.test index ff53368b..92cb8748 100644 --- a/.env.test +++ b/.env.test @@ -2,7 +2,7 @@ # To override locally, make a copy called `.env.test.local` # Refer: https://nextjs.org/docs/basic-features/environment-variables -NEXT_PUBLIC_OONI_API=https://api.ooni.io -NEXT_PUBLIC_USER_FEEDBACK_API=https://backend-hel.ooni.org +NEXT_PUBLIC_OONI_API=https://api.ooni.org +NEXT_PUBLIC_USER_FEEDBACK_API=https://api.dev.ooni.io NEXT_PUBLIC_EXPLORER_URL=https://explorer.test.ooni.org NEXT_PUBLIC_IS_TEST_ENV=1 diff --git a/components/BlockText.js b/components/BlockText.js index 3e0321be..a888fbc7 100644 --- a/components/BlockText.js +++ b/components/BlockText.js @@ -1,6 +1,6 @@ const BlockText = ({ className, ...props }) => (
) diff --git a/components/Chart.js b/components/Chart.js index 887e6c46..e78c5059 100644 --- a/components/Chart.js +++ b/components/Chart.js @@ -3,6 +3,7 @@ import GridChart, { } from 'components/aggregation/mat/GridChart' import { MATContextProvider } from 'components/aggregation/mat/MATContext' import { DetailsBox } from 'components/measurement/DetailsBox' +import SpinLoader from 'components/vendor/SpinLoader' import Link from 'next/link' import { memo, useEffect, useMemo } from 'react' import { MdBarChart, MdOutlineFileDownload } from 'react-icons/md' @@ -46,11 +47,19 @@ export const MATLink = ({ query }) => { ) } -const Chart = memo(function Chart({ - testGroup = null, - queryParams = {}, - setState, -}) { +export const ChartSpinLoader = ({ height = '300px' }) => { + return ( +
+ {/* */} + +
+ ) +} + +const Chart = ({ queryParams = {}, setState = null, headerOptions = {} }) => { const apiQuery = useMemo(() => { const qs = new URLSearchParams(queryParams).toString() return qs @@ -75,24 +84,18 @@ const Chart = memo(function Chart({ if (setState && data?.data) setState(data.data) }, [data, setState]) - const headerOptions = { probe_cc: false, subtitle: false } - return ( - //
- {!chartData && !error ? ( - - ) : ( - <> - - {!!chartData?.size && } - - )} + <> + + {!!chartData?.size && } + {error && ( ) -}) +} -export default Chart +export default memo(Chart) diff --git a/components/ChartIntersectionObserver.tsx b/components/ChartIntersectionObserver.tsx new file mode 100644 index 00000000..667973fa --- /dev/null +++ b/components/ChartIntersectionObserver.tsx @@ -0,0 +1,55 @@ +import Chart, { ChartSpinLoader } from 'components/Chart' +import { useRouter } from 'next/router' +import { useMemo } from 'react' +import { useInView } from 'react-intersection-observer' + +type ChartIntersectionObserverProps = { + domain?: string + testName?: string + headerOptions?: object +} + +const ChartIntersectionObserver = ({ + domain, + testName = 'web_connectivity', + headerOptions, +}: ChartIntersectionObserverProps) => { + const router = useRouter() + + const { + query: { since, until, probe_cc }, + } = router + + const query = useMemo( + () => ({ + axis_x: 'measurement_start_day', + axis_y: 'probe_cc', + since, + until, + test_name: testName, + ...(domain && { domain }), + ...(probe_cc && { probe_cc }), + time_grain: 'day', + }), + [domain, since, until, probe_cc, testName], + ) + + const { ref, inView } = useInView({ + triggerOnce: true, + rootMargin: '-300px 0px 0px 0px', + threshold: 0.5, + initialInView: false, + }) + + return ( +
+ {inView ? ( + + ) : ( + + )} +
+ ) +} + +export default ChartIntersectionObserver diff --git a/components/DomainChart.js b/components/DomainChart.js deleted file mode 100644 index bbb7db30..00000000 --- a/components/DomainChart.js +++ /dev/null @@ -1,93 +0,0 @@ -import GridChart, { - prepareDataForGridChart, -} from 'components/aggregation/mat/GridChart' -import { MATContextProvider } from 'components/aggregation/mat/MATContext' -import { MATLink } from 'components/Chart' -import { DetailsBox } from 'components/measurement/DetailsBox' -import { useRouter } from 'next/router' -import { memo, useEffect, useMemo } from 'react' -import { FormattedMessage, useIntl } from 'react-intl' -import { MATFetcher } from 'services/fetchers' -import useSWR from 'swr' - -const swrOptions = { - revalidateOnFocus: false, - dedupingInterval: 10 * 60 * 1000, -} - -const Chart = memo(function Chart({ queryParams = {}, setState }) { - const { - query: { probe_cc }, - } = useRouter() - const { locale } = useIntl() - - const apiQuery = useMemo(() => { - const qs = new URLSearchParams(queryParams).toString() - return qs - }, [queryParams]) - - const { data, error } = useSWR(apiQuery, MATFetcher, swrOptions) - - const [chartData, rowKeys, rowLabels] = useMemo(() => { - if (!data) { - return [null, 0] - } - - let chartData = data.data.sort((a, b) => - new Intl.Collator(locale).compare(a.probe_cc, b.probe_cc), - ) - - if (probe_cc) chartData = chartData.filter((d) => probe_cc === d.probe_cc) - - const [reshapedData, rowKeys, rowLabels] = prepareDataForGridChart( - chartData, - queryParams, - locale, - ) - - return [reshapedData, rowKeys, rowLabels] - }, [data, queryParams, probe_cc, locale]) - - useEffect(() => { - if (setState && data?.data) setState(data.data) - }, [data, setState]) - - const headerOptions = { probe_cc: false, subtitle: false } - const linkParams = { ...queryParams, ...(probe_cc && { probe_cc }) } - - return ( - // - -
-
- {!chartData && !error ? ( - - ) : ( - <> - - {!!chartData?.size && } - - )} -
- {error && ( - - - Error: {error.message} - -
{JSON.stringify(error, null, 2)}
- - } - /> - )} -
-
- ) -}) - -export default Chart diff --git a/components/FindingsSection.tsx b/components/FindingsSection.tsx new file mode 100644 index 00000000..f3312493 --- /dev/null +++ b/components/FindingsSection.tsx @@ -0,0 +1,42 @@ +import { FindingBoxSmall } from 'components/landing/HighlightBox' +import Link from 'next/link' + +interface Finding { + id: string +} + +type FindingsSectionProps = { + title: string + theme: string + findings: Finding[] +} + +const FindingsSection = ({ + title, + theme, + findings = [], +}: FindingsSectionProps) => { + return ( +
+

{title}

+ {findings.length ? ( + <> +
+ {findings.map((finding) => ( + + ))} +
+ + See all related censorship findings » + +
+
+ + ) : ( +
No findings available
+ )} +
+ ) +} + +export default FindingsSection diff --git a/components/Layout.js b/components/Layout.js index 39eac94a..ac073023 100644 --- a/components/Layout.js +++ b/components/Layout.js @@ -24,6 +24,10 @@ const Layout = ({ children, isEmbeddedView }) => { return ( pathname === '/countries' || pathname === '/domains' || + pathname === '/human-rights' || + pathname === '/social-media' || + pathname === '/news-media' || + pathname === '/circumvention' || pathname === '/networks' || pathname === '/findings' || pathname.match(/^\/country\/\S+/) diff --git a/components/MATChart.js b/components/MATChart.js index 1482c5af..493f6a11 100644 --- a/components/MATChart.js +++ b/components/MATChart.js @@ -9,6 +9,7 @@ import { useMemo } from 'react' import { useIntl } from 'react-intl' import dayjs from 'services/dayjs' import useSWR from 'swr' +import { ChartSpinLoader } from './Chart' import { FormattedMarkdownBase } from './FormattedMarkdown' axiosResponseTime(axios) @@ -86,38 +87,29 @@ const MATChart = ({ query, showFilters = true }) => { swrOptions, ) - const showLoadingIndicator = useMemo(() => isValidating, [isValidating]) return ( <> {error && } - <> - {showLoadingIndicator ? ( -

{intl.formatMessage({ id: 'General.Loading' })}

- ) : ( - <> - {data?.data?.result?.length > 0 ? ( - <> - {data && data.data.dimension_count === 0 && ( - - )} - {data && data.data.dimension_count === 1 && ( - - )} - {data && data.data.dimension_count > 1 && ( - - )} - - ) : ( - - )} - - )} - + {isValidating ? ( + + ) : ( + <> + {data && data.data.dimension_count === 0 && ( + + )} + {data && data.data.dimension_count === 1 && ( + + )} + {data && data.data.dimension_count > 1 && ( + + )} + + )}
) diff --git a/components/NavBar.js b/components/NavBar.js index 20cda3fb..57b19280 100644 --- a/components/NavBar.js +++ b/components/NavBar.js @@ -83,10 +83,25 @@ const SubMenu = () => { const menuItem = [ { - label: , - href: '/chart/circumvention', + label: , + href: '/social-media', + umami: 'navigation-social-media', + }, + { + label: , + href: '/news-media', + umami: 'navigation-news-media', + }, + { + label: , + href: '/circumvention', umami: 'navigation-circumvention', }, + // { + // label: , + // href: '/human-rights', + // umami: 'navigation-human-rights', + // }, { label: , href: '/domains', @@ -109,7 +124,7 @@ const SubMenu = () => {
-