Skip to content

Commit

Permalink
Merge pull request #41 from Vizzuality/SKY30-108-fe-implement-the-eez…
Browse files Browse the repository at this point in the history
…-layers

[SKY30-108]: EEZ legend
  • Loading branch information
agnlez authored Nov 8, 2023
2 parents 150990c + 6d72fa3 commit f6fd73a
Show file tree
Hide file tree
Showing 19 changed files with 431 additions and 38 deletions.
1 change: 1 addition & 0 deletions frontend/orval.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = {
'Fishing-protection-level',
'Fishing-protection-level-stat',
'Layer',
'Data-info',
],
},
},
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/containers/data-tool/content/map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useAtomValue, useSetAtom } from 'jotai';
import Map, { ZoomControls, Attributions, DrawControls, Drawing } from '@/components/map';
import SidebarContent from '@/components/sidebar-content';
// import Popup from '@/containers/map/popup';
import LabelsManager from '@/containers/data-tool/content/map/labels-manager';
import LayersToolbox from '@/containers/data-tool/content/map/layers-toolbox';
import { useSyncMapSettings } from '@/containers/data-tool/content/map/sync-settings';
import { cn } from '@/lib/classnames';
Expand Down Expand Up @@ -192,6 +193,7 @@ const DataToolMap: React.FC = () => {
>
{/* <Popup /> */}
</div>
<LabelsManager />
<LayersToolbox />
<ZoomControls />
<DrawControls />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useCallback, useEffect } from 'react';

import { useMap } from 'react-map-gl';

import { useSyncMapSettings } from '@/containers/data-tool/content/map/sync-settings';

const LABELS_LAYER_ID = 'country-label';

const LabelsManager = () => {
const { default: mapRef } = useMap();
const [{ labels }] = useSyncMapSettings();

const toggleLabels = useCallback(() => {
if (!mapRef) return;
const map = mapRef.getMap();

map.setLayoutProperty(LABELS_LAYER_ID, 'visibility', labels ? 'visible' : 'none');
}, [mapRef, labels]);

const handleStyleLoad = useCallback(() => {
toggleLabels();
}, [toggleLabels]);

useEffect(() => {
if (!mapRef) return;
mapRef.on('style.load', handleStyleLoad);

return () => {
mapRef.off('style.load', handleStyleLoad);
};
}, [mapRef, handleStyleLoad]);

useEffect(() => {
if (!mapRef) return;
toggleLabels();
}, [mapRef, toggleLabels]);

return null;
};

export default LabelsManager;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { ComponentProps, useCallback } from 'react';

import { LuChevronDown, LuChevronUp } from 'react-icons/lu';

Expand All @@ -8,6 +8,7 @@ import { Switch } from '@/components/ui/switch';
import {
useSyncMapLayers,
useSyncMapLayerSettings,
useSyncMapSettings,
} from '@/containers/data-tool/content/map/sync-settings';
import { useGetLayers } from '@/types/generated/layer';
import { LayerResponseDataObject } from '@/types/generated/strapi.schemas';
Expand All @@ -19,6 +20,7 @@ const TABS_ICONS_CLASSES = 'w-5 h-5 -translate-y-[2px]';
const LayersDropdown = (): JSX.Element => {
const [activeLayers, setMapLayers] = useSyncMapLayers();
const [, setLayerSettings] = useSyncMapLayerSettings();
const [{ labels }, setMapSettings] = useSyncMapSettings();

const layersQuery = useGetLayers(
{
Expand Down Expand Up @@ -51,6 +53,16 @@ const LayersDropdown = (): JSX.Element => {
[activeLayers, setLayerSettings, setMapLayers]
);

const handleLabelsChange = useCallback(
(active: Parameters<ComponentProps<typeof Switch>['onCheckedChange']>[0]) => {
setMapSettings((prev) => ({
...prev,
labels: active,
}));
},
[setMapSettings]
);

return (
<div className="space-y-3">
<Collapsible defaultOpen={Boolean(activeLayers.length)}>
Expand Down Expand Up @@ -83,7 +95,7 @@ const LayersDropdown = (): JSX.Element => {
</ul>
</CollapsibleContent>
</Collapsible>
<Collapsible>
<Collapsible defaultOpen={labels}>
<CollapsibleTrigger
className={`${COLLAPSIBLE_TRIGGER_CLASSES} pb-0 data-[state=open]:pb-2`}
>
Expand All @@ -94,11 +106,7 @@ const LayersDropdown = (): JSX.Element => {
<CollapsibleContent>
<ul className="my-3 flex flex-col space-y-5">
<li className="flex items-start gap-2">
<Switch
id="labels-switch"
// checked={isActive}
onCheckedChange={() => {}}
/>
<Switch id="labels-switch" checked={labels} onCheckedChange={handleLabelsChange} />
<Label htmlFor="labels-switch" className="cursor-pointer">
Labels
</Label>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Icon from '@/components/ui/icon';
import { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
import EEZIcon from '@/styles/icons/eez.svg?sprite';
import InfoIcon from '@/styles/icons/info.svg?sprite';
import SelectedEEZIcon from '@/styles/icons/selected-eez.svg?sprite';
import SeveralEEZIcon from '@/styles/icons/several-eez.svg?sprite';
import { useGetDataInfos } from '@/types/generated/data-info';

const ITEM_LIST_CLASSES = 'flex items-center space-x-2';
const ICON_CLASSES = 'h-7 w-7';

const EEZLayerLegend = () => {
const EEZInfoQuery = useGetDataInfos(
{
filters: {
slug: 'eez-legend',
},
},
{
query: {
select: ({ data }) => data?.[0].attributes,
},
}
);

return (
<ul className="space-y-3 font-mono text-xs">
<li className={ITEM_LIST_CLASSES}>
<Icon icon={EEZIcon} className={ICON_CLASSES} />
<span>EEZs</span>
</li>
<li className={ITEM_LIST_CLASSES}>
<Icon icon={SelectedEEZIcon} className={ICON_CLASSES} />
<span>Selected EEZ</span>
</li>
<li className={ITEM_LIST_CLASSES}>
<Icon icon={SeveralEEZIcon} className={ICON_CLASSES} />
<div className="max-w-[195px] space-x-1">
<span>
Area corresponding to more <br /> than one EEZ
</span>
<TooltipProvider skipDelayDuration={0} delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<button type="button" className="translate-y-[4px]">
<Icon icon={InfoIcon} className="h-4 w-4" />
</button>
</TooltipTrigger>
<TooltipContent>
<div className="max-w-[235px] p-4">{EEZInfoQuery.data?.content}</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</li>
</ul>
);
};

export default EEZLayerLegend;
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { FC, useCallback } from 'react';

import { ChevronUp, CircleDashed, Eye, EyeOff, MoveUp, X } from 'lucide-react';
import { ChevronUp } from 'lucide-react';
import { HiEye, HiEyeOff } from 'react-icons/hi';

import { Accordion, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/ui/accordion';
import { Button } from '@/components/ui/button';
import Icon from '@/components/ui/icon';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Slider } from '@/components/ui/slider';
Expand All @@ -13,11 +20,15 @@ import {
useSyncMapLayers,
} from '@/containers/data-tool/content/map/sync-settings';
import { cn } from '@/lib/classnames';
import ArrowDownIcon from '@/styles/icons/arrow-down.svg?sprite';
import ArrowTopIcon from '@/styles/icons/arrow-top.svg?sprite';
import CloseIcon from '@/styles/icons/close.svg?sprite';
import OpacityIcon from '@/styles/icons/opacity.svg?sprite';
import { useGetLayers } from '@/types/generated/layer';
import { LayerResponseDataObject } from '@/types/generated/strapi.schemas';
// import { LayerTyped } from '@/types/layers';
import { LayerTyped } from '@/types/layers';

// import LegendItems from './items';
import LegendItem from './item';

const Legend: FC = () => {
const [activeLayers, setMapLayers] = useSyncMapLayers();
Expand Down Expand Up @@ -140,7 +151,7 @@ const Legend: FC = () => {
})}
onValueChange={onToggleAccordion}
>
{layersQuery.data?.map(({ id, attributes: { title } }, index) => {
{layersQuery.data?.map(({ id, attributes: { title, legend_config } }, index) => {
const isFirst = index === 0;
const isLast = index + 1 === layersQuery.data.length;

Expand Down Expand Up @@ -175,7 +186,7 @@ const Legend: FC = () => {
</TooltipProvider>
<TooltipProvider>
<div className="flex shrink-0 items-center gap-0.5">
<Tooltip>
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
<Button
type="button"
Expand All @@ -185,7 +196,7 @@ const Legend: FC = () => {
onClick={() => onMoveLayerUp(id)}
>
<span className="sr-only">Move up</span>
<MoveUp className="h-4 w-4" aria-hidden />
<Icon icon={ArrowTopIcon} className="h-4 w-4 " />
</Button>
</TooltipTrigger>
<TooltipContent>Move up</TooltipContent>
Expand All @@ -200,7 +211,7 @@ const Legend: FC = () => {
onClick={() => onMoveLayerDown(id)}
>
<span className="sr-only">Move down</span>
<MoveUp className="h-4 w-4 rotate-180" aria-hidden />
<Icon icon={ArrowDownIcon} className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Move down</TooltipContent>
Expand All @@ -211,7 +222,7 @@ const Legend: FC = () => {
<PopoverTrigger asChild>
<Button type="button" variant="ghost" size="icon-sm">
<span className="sr-only">Change opacity</span>
<CircleDashed className="h-4 w-4" aria-hidden />
<Icon icon={OpacityIcon} className="h-4 w-4" />
</Button>
</PopoverTrigger>
</TooltipTrigger>
Expand All @@ -237,8 +248,8 @@ const Legend: FC = () => {
onClick={() => onToggleLayerVisibility(id, !isVisible)}
>
<span className="sr-only">{isVisible ? 'Hide' : 'Show'}</span>
{isVisible && <Eye className="h-4 w-4" aria-hidden />}
{!isVisible && <EyeOff className="h-4 w-4" aria-hidden />}
{isVisible && <HiEye className="h-4 w-4" aria-hidden />}
{!isVisible && <HiEyeOff className="h-4 w-4" aria-hidden />}
</Button>
</TooltipTrigger>
<TooltipContent>{isVisible ? 'Hide' : 'Show'}</TooltipContent>
Expand All @@ -255,17 +266,17 @@ const Legend: FC = () => {
}}
>
<span className="sr-only">Remove</span>
<X className="h-4 w-4" aria-hidden />
<Icon icon={CloseIcon} className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent>Remove</TooltipContent>
</Tooltip>
</div>
</TooltipProvider>
</div>
{/* <AccordionContent className="pt-2">
<LegendItems items={legend_config as LayerTyped['legend_config']} />
</AccordionContent> */}
<AccordionContent className="pt-2">
<LegendItem config={legend_config as LayerTyped['legend_config']} />
</AccordionContent>
</AccordionItem>
);
})}
Expand Down
Loading

0 comments on commit f6fd73a

Please sign in to comment.