Skip to content

Commit

Permalink
Merge pull request #68 from Vizzuality/fix/client/location-list-limits
Browse files Browse the repository at this point in the history
fixes issue loading locations due to pagination
  • Loading branch information
SARodrigues authored Nov 22, 2023
2 parents 285d7e1 + 5ede5ee commit cb7f1ed
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 1,350 deletions.
2 changes: 1 addition & 1 deletion frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const nextConfig = {
return [
{
source: '/dashboard',
destination: '/dashboard/worldwide',
destination: '/dashboard/GLOB',
permanent: false,
},
{
Expand Down
37 changes: 25 additions & 12 deletions frontend/src/containers/data-tool/content/details/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
import { useMemo } from 'react';

import { useAtomValue } from 'jotai';
import { useRouter } from 'next/router';

import { useQueryClient } from '@tanstack/react-query';

import { Button } from '@/components/ui/button';
import tablesSettings from '@/containers/data-tool/content/details/tables-settings';
import { useSyncDataToolContentSettings } from '@/containers/data-tool/sync-settings';
import { locationAtom } from '@/store/location';
import { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

const DataToolDetails: React.FC = () => {
const [, setSettings] = useSyncDataToolContentSettings();
const location = useAtomValue(locationAtom);
const {
query: { locationCode },
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);

const handleOnCloseClick = () => {
setSettings((prevSettings) => ({ ...prevSettings, showDetails: false }));
};

const table = useMemo(() => {
// TODO: Improve to support more entries (although not needed right now)
const tableSettings = tablesSettings.worldwideRegion.locationTypes.includes(location.type)
? tablesSettings.worldwideRegion
: tablesSettings.countryHighseas;
if (location) {
// TODO: Improve to support more entries (although not needed right now)
const tableSettings = tablesSettings.worldwideRegion.locationTypes.includes(location.type)
? tablesSettings.worldwideRegion
: tablesSettings.countryHighseas;

const parsedTitle = tableSettings.title[location.type].replace('{location}', location.name);
const parsedTitle = tableSettings.title[location.type].replace('{location}', location.name);

return {
title: parsedTitle,
component: tableSettings.component,
};
return {
title: parsedTitle,
component: tableSettings.component,
};
}
}, [location]);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import { useMemo, useState } from 'react';

import { useAtomValue } from 'jotai';
import { useRouter } from 'next/router';

import { useQueryClient } from '@tanstack/react-query';

import { applyFilters } from '@/containers/data-tool/content/details/helpers';
import Table from '@/containers/data-tool/content/details/table';
import useColumns from '@/containers/data-tool/content/details/tables/global-regional/useColumns';
import { locationAtom } from '@/store/location';
import { useGetLocations } from '@/types/generated/location';
import type { LocationListResponseDataItem } from '@/types/generated/strapi.schemas';
import type {
LocationGroupsDataItemAttributes,
LocationListResponseDataItem,
} from '@/types/generated/strapi.schemas';

const DATA_YEAR = 2023;

const GlobalRegionalTable: React.FC = () => {
const location = useAtomValue(locationAtom);
const {
query: { locationCode },
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);

const [filters, setFilters] = useState({
// ! This shouldn't be hardcoded. The setup needs to be able to work the same without any default filters here.
Expand Down Expand Up @@ -65,7 +78,7 @@ const GlobalRegionalTable: React.FC = () => {
? {
groups: {
code: {
$eq: location.code,
$eq: location?.code,
},
},
}
Expand Down Expand Up @@ -135,9 +148,9 @@ const GlobalRegionalTable: React.FC = () => {
const parsedData = useMemo(() => {
return locationsData.map(({ attributes: location }) => {
// Base stats needed for calculations
const coverageStats = location?.protection_coverage_stats?.data;
const mpaaStats = location?.mpaa_protection_level_stats?.data;
const lfpStats = location?.fishing_protection_level_stats?.data;
const coverageStats = location.protection_coverage_stats?.data;
const mpaaStats = location.mpaa_protection_level_stats?.data;
const lfpStats = location.fishing_protection_level_stats?.data;

// Coverage calculations
const protectedArea = coverageStats.reduce(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import { useMemo, useState } from 'react';

import { useAtomValue } from 'jotai';
import { useRouter } from 'next/router';

import { useQueryClient } from '@tanstack/react-query';

import { applyFilters } from '@/containers/data-tool/content/details/helpers';
import Table from '@/containers/data-tool/content/details/table';
import useColumns from '@/containers/data-tool/content/details/tables/national-highseas/useColumns';
import { locationAtom } from '@/store/location';
import { useGetMpaProtectionCoverageStats } from '@/types/generated/mpa-protection-coverage-stat';
import { MpaProtectionCoverageStatListResponseDataItem } from '@/types/generated/strapi.schemas';
import {
LocationGroupsDataItemAttributes,
MpaProtectionCoverageStatListResponseDataItem,
} from '@/types/generated/strapi.schemas';

const NationalHighseasTable: React.FC = () => {
const location = useAtomValue(locationAtom);
const {
query: { locationCode },
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);

const [filters, setFilters] = useState({
// ! This shouldn't be hardcoded. The setup needs to be able to work the same without any default filters here.
Expand All @@ -36,7 +49,7 @@ const NationalHighseasTable: React.FC = () => {
filters: {
location: {
code: {
$eq: location.code,
$eq: location?.code,
},
},
},
Expand Down
17 changes: 6 additions & 11 deletions frontend/src/containers/data-tool/content/map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import {
popupAtom,
} from '@/store/map';
import { useGetLayers } from '@/types/generated/layer';
import { getGetLocationsQueryOptions } from '@/types/generated/location';
import { LocationListResponse, LocationResponseDataObject } from '@/types/generated/strapi.schemas';
import { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';
import { LayerTyped } from '@/types/layers';

const LayerManager = dynamic(() => import('@/containers/data-tool/content/map/layer-manager'), {
Expand All @@ -39,7 +38,7 @@ const DataToolMap: React.FC = () => {
const { locationCode } = useParams();
const hoveredPolygonId = useRef<string | number | null>(null);

const locationData = queryClient.getQueryData<LocationResponseDataObject>([
const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);
Expand Down Expand Up @@ -128,15 +127,11 @@ const DataToolMap: React.FC = () => {
}
}, [map, hoveredPolygonId]);

const bounds = customBbox ?? (locationData?.attributes?.bounds as LngLatBoundsLike);
const bounds = customBbox ?? (location?.bounds as LngLatBoundsLike);

useEffect(() => {
const { queryKey } = getGetLocationsQueryOptions();
const d = queryClient.getQueryData<LocationListResponse>(queryKey);
if (d) {
const location = d.data.find(({ attributes }) => attributes.code === locationCode);

map?.fitBounds(location.attributes.bounds as LngLatBoundsLike, {
if (location && map) {
map.fitBounds(location.bounds as LngLatBoundsLike, {
padding: {
top: 0,
bottom: 0,
Expand All @@ -145,7 +140,7 @@ const DataToolMap: React.FC = () => {
},
});
}
}, [queryClient, locationCode, map]);
}, [location, map]);

return (
<div className="absolute left-0 h-full w-full">
Expand Down
20 changes: 16 additions & 4 deletions frontend/src/containers/data-tool/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import { useAtom, useAtomValue } from 'jotai';
import { useRouter } from 'next/router';

import { useQueryClient } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import { ChevronLeft } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { cn } from '@/lib/classnames';
import { sidebarAtom } from '@/store/data-tool';
import { locationAtom } from '@/store/location';
import { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

import DetailsButton from './details-button';
import LocationSelector from './location-selector';
import Widgets from './widgets';

const DataToolSidebar: React.FC = () => {
const location = useAtomValue(locationAtom);
const {
query: { locationCode },
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);

const [isSidebarOpen, setSidebarOpen] = useAtom(sidebarAtom);

Expand All @@ -39,7 +51,7 @@ const DataToolSidebar: React.FC = () => {
<CollapsibleContent className="relative top-0 left-0 z-20 h-full flex-shrink-0 bg-white fill-mode-none data-[state=closed]:animate-out-absolute data-[state=open]:animate-in-absolute data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left md:w-[430px]">
<div className="h-full w-full overflow-y-scroll border-r border-black pb-12">
<div className="border-b border-black px-4 pt-4 pb-2 md:px-8">
<h1 className="text-5xl font-black">{location.name}</h1>
<h1 className="text-5xl font-black">{location?.name}</h1>
<LocationSelector className="my-2" />
</div>
<div className="">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useCallback, useState } from 'react';

import { useRouter } from 'next/router';

import { useAtomValue } from 'jotai';
import { useQueryClient } from '@tanstack/react-query';
import { Check } from 'lucide-react';

import {
Expand All @@ -15,8 +15,8 @@ import {
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { PAGES } from '@/constants/pages';
import { cn } from '@/lib/classnames';
import { locationAtom } from '@/store/location';
import { useGetLocations } from '@/types/generated/location';
import { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

import { useDataToolSearchParams } from '../../content/map/sync-settings';

Expand All @@ -25,20 +25,35 @@ type LocationSelectorProps = {
};

const LocationSelector: React.FC<LocationSelectorProps> = ({ className }) => {
const location = useAtomValue(locationAtom);
const { push } = useRouter();
const {
query: { locationCode },
push,
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);
const searchParams = useDataToolSearchParams();

const [locationPopoverOpen, setLocationPopoverOpen] = useState(false);
const { data: locationsData } = useGetLocations(null, {
query: {
placeholderData: { data: [] },
select: ({ data }) => data,
const { data: locationsData } = useGetLocations(
{
'pagination[limit]': -1,
sort: 'name:asc',
},
});
{
query: {
placeholderData: { data: [] },
select: ({ data }) => data,
},
}
);

const handleLocationSelected = useCallback(
async (locationCode: string) => {
async (locationCode: LocationGroupsDataItemAttributes['code']) => {
setLocationPopoverOpen(false);

await push(`${PAGES.dataTool}/${locationCode.toUpperCase()}?${searchParams.toString()}`);
Expand All @@ -56,7 +71,7 @@ const LocationSelector: React.FC<LocationSelectorProps> = ({ className }) => {
<Command label="Search country or region">
<CommandInput placeholder="Search country or region" />
<CommandEmpty>No result</CommandEmpty>
<CommandGroup className="mt-4 max-h-64 overflow-y-scroll">
<CommandGroup className="mt-4 max-h-64 overflow-y-auto">
{locationsData.map(({ attributes }) => {
const { name, code, type } = attributes;

Expand All @@ -71,7 +86,7 @@ const LocationSelector: React.FC<LocationSelectorProps> = ({ className }) => {
<Check
className={cn(
'relative top-1 mr-2 inline-block h-4 w-4 flex-shrink-0',
location.code === code ? 'opacity-100' : 'opacity-0'
location?.code === code ? 'opacity-100' : 'opacity-0'
)}
/>
{name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import HorizontalBarChart from '@/components/charts/horizontal-bar-chart';
import Widget from '@/components/widget';
import { HABITAT_CHART_COLORS } from '@/constants/habitat-chart-colors';
import { useGetHabitatStats } from '@/types/generated/habitat-stat';
import type { Location } from '@/types/generated/strapi.schemas';
import type { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

type HabitatWidgetProps = {
location: Location;
location: LocationGroupsDataItemAttributes;
};

const HabitatWidget: React.FC<HabitatWidgetProps> = ({ location }) => {
Expand Down
17 changes: 14 additions & 3 deletions frontend/src/containers/data-tool/sidebar/widgets/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { useAtomValue } from 'jotai';
import { useRouter } from 'next/router';

import { locationAtom } from '@/store/location';
import { useQueryClient } from '@tanstack/react-query';

import { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

import HabitatWidget from './habitat';
import MarineConservationWidget from './marine-conservation';
import ProtectionTypesWidget from './protection-types';

const DataToolWidgets: React.FC = () => {
const location = useAtomValue(locationAtom);
const {
query: { locationCode },
} = useRouter();

const queryClient = useQueryClient();

const location = queryClient.getQueryData<LocationGroupsDataItemAttributes>([
'locations',
locationCode,
]);

return (
<div className="flex flex-col divide-y-[1px] divide-black font-mono">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { groupBy } from 'lodash-es';
import ConservationChart from '@/components/charts/conservation-chart';
import Widget from '@/components/widget';
import { useGetProtectionCoverageStats } from '@/types/generated/protection-coverage-stat';
import type { Location } from '@/types/generated/strapi.schemas';
import type { LocationGroupsDataItemAttributes } from '@/types/generated/strapi.schemas';

type MarineConservationWidgetProps = {
location: Location;
location: LocationGroupsDataItemAttributes;
};

const MarineConservationWidget: React.FC<MarineConservationWidgetProps> = ({ location }) => {
Expand Down
Loading

0 comments on commit cb7f1ed

Please sign in to comment.