Skip to content

Commit

Permalink
Add thematic pages
Browse files Browse the repository at this point in the history
  • Loading branch information
majakomel committed Oct 23, 2024
1 parent fc98fef commit 5450edd
Show file tree
Hide file tree
Showing 61 changed files with 2,816 additions and 2,097 deletions.
2 changes: 1 addition & 1 deletion components/BlockText.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const BlockText = ({ className, ...props }) => (
<div
className={`bg-gray-50 border-s-[10px] text-base border-blue-500 p-3 font-base ${className}`}
className={`bg-gray-50 border-s-[10px] border-blue-500 p-3 font-base ${className}`}
{...props}
/>
)
Expand Down
43 changes: 24 additions & 19 deletions components/Chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -46,11 +47,19 @@ export const MATLink = ({ query }) => {
)
}

const Chart = memo(function Chart({
testGroup = null,
queryParams = {},
setState,
}) {
export const ChartSpinLoader = ({ height = '300px' }) => {
return (
<div
className="bg-gray-100 flex items-center justify-center p-6"
style={{ height }}
>
{/* <FormattedMessage id="General.Loading" /> */}
<SpinLoader />
</div>
)
}

const Chart = ({ queryParams = {}, setState = null, headerOptions = {} }) => {
const apiQuery = useMemo(() => {
const qs = new URLSearchParams(queryParams).toString()
return qs
Expand All @@ -75,20 +84,18 @@ const Chart = memo(function Chart({
if (setState && data?.data) setState(data.data)
}, [data, setState])

const headerOptions = { probe_cc: false, subtitle: false }

return (
// <MATContextProvider key={name} test_name={name} {...queryParams}>
<MATContextProvider {...queryParams}>
<div className="flex flex-col">
{!chartData && !error ? (
<FormattedMessage id="General.Loading" />
<ChartSpinLoader />
) : (
<>
<GridChart
data={chartData}
rowKeys={rowKeys}
rowLabels={rowLabels}
header={headerOptions}
/>
{!!chartData?.size && <MATLink query={queryParams} />}
</>
Expand All @@ -97,20 +104,18 @@ const Chart = memo(function Chart({
<DetailsBox
collapsed={false}
content={
<>
<details>
<summary>
<span>Error: {error.message}</span>
</summary>
<pre>{JSON.stringify(error, null, 2)}</pre>
</details>
</>
<details>
<summary>
<span>Error: {error.message}</span>
</summary>
<pre>{JSON.stringify(error, null, 2)}</pre>
</details>
}
/>
)}
</div>
</MATContextProvider>
)
})
}

export default Chart
export default memo(Chart)
59 changes: 59 additions & 0 deletions components/ChartWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Chart, { ChartSpinLoader } from 'components/Chart'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import { useInView } from 'react-intersection-observer'

type ChartWrapperProps = {
domain?: string
testName?: string
headerOptions?: object
}

const ChartWrapper = ({
domain,
testName = 'web_connectivity',
headerOptions,
}: ChartWrapperProps) => {
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 (
<div ref={ref}>
{inView ? (
<Chart
// testName={testName}
queryParams={query}
headerOptions={headerOptions}
/>
) : (
<ChartSpinLoader />
)}
</div>
)
}

export default ChartWrapper
2 changes: 0 additions & 2 deletions components/DomainChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,9 @@ const Chart = memo(function Chart({ queryParams = {}, setState }) {
if (setState && data?.data) setState(data.data)
}, [data, setState])

const headerOptions = { probe_cc: false, subtitle: false }
const linkParams = { ...queryParams, ...(probe_cc && { probe_cc }) }

return (
// <MATContextProvider key={name} test_name={name} {...queryParams}>
<MATContextProvider {...queryParams}>
<div className="flex flex-col">
<div>
Expand Down
44 changes: 44 additions & 0 deletions components/FindingsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { FindingBox } 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 (
<section className="mb-12">
<h3>{title}</h3>
{findings.length ? (
<>
<div className="grid my-8 gap-6 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{findings.map((finding) => (
<FindingBox key={finding.id} incident={finding} />
))}
</div>
<div className="flex my-4 justify-center">
<Link href={`/findings?theme=${theme}`}>
<button type="button" className="btn btn-primary-hollow">
See more
</button>
</Link>
</div>
</>
) : (
<div className="my-3">No findings available</div>
)}
</section>
)
}

export default FindingsSection
6 changes: 5 additions & 1 deletion components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const Layout = ({ children }) => {
return (
pathname === '/countries' ||
pathname === '/domains' ||
pathname === '/human-rights' ||
pathname === '/social-media' ||
pathname === '/news-media' ||
pathname === '/circumvention' ||
pathname === '/networks' ||
pathname === '/findings' ||
pathname.match(/^\/country\/\S+/)
Expand All @@ -31,7 +35,7 @@ const Layout = ({ children }) => {

return (
<UserProvider>
<div className="site text-sm flex flex-col min-h-[100vh]">
<div className="site flex flex-col min-h-[100vh]">
<div className="flex-[1_0_auto]">
<Header />
{navbarSticky ? (
Expand Down
55 changes: 28 additions & 27 deletions components/MATChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -87,37 +88,37 @@ const MATChart = ({ query, showFilters = true }) => {
)

const showLoadingIndicator = useMemo(() => isValidating, [isValidating])

return (
<>
<MATContextProvider queryParams={query}>
{error && <NoCharts message={error?.info ?? JSON.stringify(error)} />}
<>
{showLoadingIndicator ? (
<h2>{intl.formatMessage({ id: 'General.Loading' })}</h2>
) : (
<>
{data?.data?.result?.length > 0 ? (
<>
{data && data.data.dimension_count === 0 && (
<FunnelChart data={data.data.result} />
)}
{data && data.data.dimension_count === 1 && (
<StackedBarChart data={data.data.result} query={query} />
)}
{data && data.data.dimension_count > 1 && (
<TableView
data={data.data.result}
query={query}
showFilters={showFilters}
/>
)}
</>
) : (
<NoCharts />
)}
</>
)}
</>
{showLoadingIndicator ? (
// <h2>{intl.formatMessage({ id: 'General.Loading' })}</h2>
<ChartSpinLoader height={580} />
) : (
<>
{data?.data?.result?.length > 0 ? (
<>
{data && data.data.dimension_count === 0 && (
<FunnelChart data={data.data.result} />
)}
{data && data.data.dimension_count === 1 && (
<StackedBarChart data={data.data.result} query={query} />
)}
{data && data.data.dimension_count > 1 && (
<TableView
data={data.data.result}
query={query}
showFilters={showFilters}
/>
)}
</>
) : (
<NoCharts />
)}
</>
)}
</MATContextProvider>
</>
)
Expand Down
25 changes: 20 additions & 5 deletions components/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,23 @@ const SubMenu = () => {

const menuItem = [
{
label: <FormattedMessage id="Navbar.Charts.Circumvention" />,
href: '/chart/circumvention',
label: <FormattedMessage id="Navbar.SocialMedia" />,
href: '/social-media',
umami: 'navigation-social-media',
},
{
label: <FormattedMessage id="Navbar.NewsMedia" />,
href: '/news-media',
umami: 'navigation-news-media',
},
// {
// label: <FormattedMessage id="Navbar.HumanRights" />,
// href: '/human-rights',
// umami: 'navigation-human-rights',
// },
{
label: <FormattedMessage id="Navbar.Circumvention" />,
href: '/circumvention',
umami: 'navigation-circumvention',
},
{
Expand Down Expand Up @@ -170,7 +185,7 @@ export const NavBar = ({ color }) => {
onClick={() => setShowMenu(!showMenu)}
/>
<div
className={`z-[9999] lg:block ${showMenu ? 'block overflow-y-scroll max-h-full p-8 text-base fixed top-0 right-0 bg-gray-50' : 'hidden'}`}
className={`z-[9999] lg:block ${showMenu ? 'block overflow-y-scroll max-h-full p-8 fixed top-0 right-0 bg-gray-50' : 'hidden'}`}
>
{showMenu && (
<div className="flex justify-end">
Expand All @@ -182,7 +197,7 @@ export const NavBar = ({ color }) => {
</div>
)}
<div
className={`flex gap-4 lg:gap-8 ${showMenu && 'pt-2 flex-col items-start [&>a]:border-black [&>a]:hover:border-black [&>*]:opacity-100 [&>*]:text-black [&>*]:hover:text-black'}`}
className={`flex gap-4 lg:gap-8 text-sm ${showMenu && 'pt-2 flex-col items-start [&>a]:border-black [&>a]:hover:border-black [&>*]:opacity-100 [&>*]:text-black [&>*]:hover:text-black'}`}
>
<NavItem
label={<FormattedMessage id="Navbar.Findings" />}
Expand All @@ -191,7 +206,7 @@ export const NavBar = ({ color }) => {
/>
<NavItem
label={<FormattedMessage id="Navbar.Censorship" />}
href="/chart/circumvention"
href="/social-media"
data-umami-event="navigation-censorship"
/>
<NavItem
Expand Down
26 changes: 26 additions & 0 deletions components/ReportsSection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { FormattedMessage } from 'react-intl'
import { FeaturedArticle } from './country/Overview'
import { BoxWithTitle } from './country/boxes'

const ReportsSection = ({ title, reports }) => {
return (
<BoxWithTitle title={title}>
{/* <section className="my-12"> */}
{/* <h3>{title}</h3> */}
{reports?.length === 0 ? (
<FormattedMessage id="Country.Overview.FeaturedResearch.None" />
) : (
<ul>
{reports?.map((article, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<li key={index}>
<FeaturedArticle link={article.href} title={article.title} />
</li>
))}
</ul>
)}
</BoxWithTitle>
)
}

export default ReportsSection
Loading

0 comments on commit 5450edd

Please sign in to comment.