From ce83b06bb99680c124b0e76b532ffbc739c29f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Prod=27homme?= Date: Wed, 20 Nov 2024 14:31:03 +0100 Subject: [PATCH 1/3] feat(client): Display dataset metadata in dialog --- client/package.json | 1 + client/src/components/dataset-card/index.tsx | 24 +- .../src/components/dataset-metadata/index.tsx | 93 ++ client/src/components/markdown/index.tsx | 32 + .../navigation/navigation-desktop/index.tsx | 2 +- .../panels/contextual-layers/index.tsx | 11 +- .../panels/contextual-layers/item.tsx | 29 +- .../src/components/panels/drought/index.tsx | 11 +- client/src/components/panels/flood/index.tsx | 11 +- .../panels/hydrometeorological/index.tsx | 1 + client/src/components/ui/dialog.tsx | 4 +- client/src/hooks/use-datasets-by-sub-topic.ts | 7 +- client/src/svgs/question-mark.svg | 6 + client/yarn.lock | 804 +++++++++++++++++- 14 files changed, 1012 insertions(+), 24 deletions(-) create mode 100644 client/src/components/dataset-metadata/index.tsx create mode 100644 client/src/components/markdown/index.tsx create mode 100644 client/src/svgs/question-mark.svg diff --git a/client/package.json b/client/package.json index 5a6ba5b..da63d2d 100644 --- a/client/package.json +++ b/client/package.json @@ -57,6 +57,7 @@ "react": "18.3.1", "react-dom": "18.3.1", "react-map-gl": "7.1.7", + "react-markdown": "9.0.1", "tailwind-merge": "2.5.4", "tailwindcss-animate": "1.0.7", "tailwindcss-border-image": "1.1.2", diff --git a/client/src/components/dataset-card/index.tsx b/client/src/components/dataset-card/index.tsx index fe47819..cedca6d 100644 --- a/client/src/components/dataset-card/index.tsx +++ b/client/src/components/dataset-card/index.tsx @@ -6,7 +6,9 @@ import Link from "next/link"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import * as React from "react"; +import DatasetMetadata from "@/components/dataset-metadata"; import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import MonthPicker from "@/components/ui/month-picker"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; @@ -25,7 +27,8 @@ import ChevronDownIcon from "@/svgs/chevron-down.svg"; import DownloadIcon from "@/svgs/download.svg"; import PauseIcon from "@/svgs/pause.svg"; import PlayIcon from "@/svgs/play.svg"; -import { DatasetLayersDataItem } from "@/types/generated/strapi.schemas"; +import QuestionMarkIcon from "@/svgs/question-mark.svg"; +import { DatasetLayersDataItem, MetadataItemComponent } from "@/types/generated/strapi.schemas"; import { LayerParamsConfig } from "@/types/layer"; import { @@ -40,9 +43,10 @@ interface DatasetCardProps { name: string; defaultLayerId: number | undefined; layers: DatasetLayersDataItem[]; + metadata?: MetadataItemComponent; } -const DatasetCard = ({ id, name, defaultLayerId, layers }: DatasetCardProps) => { +const DatasetCard = ({ id, name, defaultLayerId, layers, metadata }: DatasetCardProps) => { const [layersConfiguration, { addLayer, updateLayer, removeLayer }] = useMapLayers(); const defaultSelectedLayerId = useMemo( @@ -235,6 +239,22 @@ const DatasetCard = ({ id, name, defaultLayerId, layers }: DatasetCardProps) => )} + {!!metadata && ( + + + + + + + + + )} { + return ( + <> + + {name} + +
+ {!!metadata.full_name && ( +
+
Full name
+
{metadata.full_name}
+
+ )} + {!!metadata.source && ( +
+
Source
+
{metadata.source}
+
+ )} + {!!metadata.website && ( +
+
Website
+
+ + {metadata.website} + +
+
+ )} + {!!metadata.description && ( +
+
Description
+
{metadata.description}
+
+ )} + {!!metadata.main_applications && ( +
+
Main applications
+
+ {metadata.main_applications} +
+
+ )} + {!!metadata.temporal_resolution && ( +
+
Temporal resolution
+
+ {metadata.temporal_resolution} +
+
+ )} + {!!metadata.temporal_coverage && ( +
+
Temporal coverage
+
+ {metadata.temporal_coverage} +
+
+ )} + {!!metadata.spatial_resolution && ( +
+
Spatial resolution
+
{metadata.spatial_resolution}
+
+ )} + {!!metadata.units && ( +
+
Units
+
{metadata.units}
+
+ )} +
+ + ); +}; + +export default DatasetMetadata; diff --git a/client/src/components/markdown/index.tsx b/client/src/components/markdown/index.tsx new file mode 100644 index 0000000..79f2e13 --- /dev/null +++ b/client/src/components/markdown/index.tsx @@ -0,0 +1,32 @@ +import Link from "next/link"; +import ReactMarkdown from "react-markdown"; + +interface MarkdownProps { + children: string | null | undefined; +} + +const Markdown = ({ children }: MarkdownProps) => { + return ( +
    {children}
, + ol: ({ children }) =>
    {children}
, + a: ({ children, href }) => ( + + {children} + + ), + }} + > + {children} +
+ ); +}; + +export default Markdown; diff --git a/client/src/components/navigation/navigation-desktop/index.tsx b/client/src/components/navigation/navigation-desktop/index.tsx index 8c62e87..b8e8419 100644 --- a/client/src/components/navigation/navigation-desktop/index.tsx +++ b/client/src/components/navigation/navigation-desktop/index.tsx @@ -46,7 +46,7 @@ const NavigationDesktop = () => { - + diff --git a/client/src/components/panels/contextual-layers/index.tsx b/client/src/components/panels/contextual-layers/index.tsx index b7d9bc4..ee6965a 100644 --- a/client/src/components/panels/contextual-layers/index.tsx +++ b/client/src/components/panels/contextual-layers/index.tsx @@ -9,10 +9,12 @@ import XMarkIcon from "@/svgs/xmark.svg"; import Item from "./item"; const ContextualLayersPanel = () => { - const { data, isLoading } = useDatasetsBySubTopic("contextual", "sub_topic.name,name", [ - "layer", - "download_link", - ]); + const { data, isLoading } = useDatasetsBySubTopic( + "contextual", + "sub_topic.name,name", + ["layer", "download_link"], + true, + ); return ( <> @@ -75,6 +77,7 @@ const ContextualLayersPanel = () => { id: dataset.layers[0].id!, name: dataset.layers[0].attributes!.name!, downloadLink: dataset.layers[0].attributes!.download_link, + metadata: dataset.metadata, }))} /> ))} diff --git a/client/src/components/panels/contextual-layers/item.tsx b/client/src/components/panels/contextual-layers/item.tsx index f90cd25..9642f50 100644 --- a/client/src/components/panels/contextual-layers/item.tsx +++ b/client/src/components/panels/contextual-layers/item.tsx @@ -1,16 +1,25 @@ import Link from "next/link"; +import * as React from "react"; +import DatasetMetadata from "@/components/dataset-metadata"; import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import useMapLayers from "@/hooks/use-map-layers"; import { cn } from "@/lib/utils"; import DownloadIcon from "@/svgs/download.svg"; -import { Dataset, Layer } from "@/types/generated/strapi.schemas"; +import QuestionMarkIcon from "@/svgs/question-mark.svg"; +import { Dataset, Layer, MetadataItemComponent } from "@/types/generated/strapi.schemas"; interface ItemProps { name: Dataset["name"]; - layers: { id: number; name: Layer["name"]; downloadLink?: Layer["download_link"] }[]; + layers: { + id: number; + name: Layer["name"]; + downloadLink?: Layer["download_link"]; + metadata?: MetadataItemComponent; + }[]; } const Item = ({ name, layers }: ItemProps) => { @@ -49,6 +58,22 @@ const Item = ({ name, layers }: ItemProps) => { /> + {!!layer.metadata && ( + + + + + + + + + )} id === layer.id) !== -1} diff --git a/client/src/components/panels/drought/index.tsx b/client/src/components/panels/drought/index.tsx index 478b586..2dc8c4b 100644 --- a/client/src/components/panels/drought/index.tsx +++ b/client/src/components/panels/drought/index.tsx @@ -6,11 +6,12 @@ import { Skeleton } from "@/components/ui/skeleton"; import useDatasetsBySubTopic from "@/hooks/use-datasets-by-sub-topic"; const DroughtPanel = () => { - const { data, isLoading } = useDatasetsBySubTopic("drought", "sub_topic.name:desc,name", [ - "name", - "params_config", - "download_link", - ]); + const { data, isLoading } = useDatasetsBySubTopic( + "drought", + "sub_topic.name:desc,name", + ["name", "params_config", "download_link"], + true, + ); return (
diff --git a/client/src/components/panels/flood/index.tsx b/client/src/components/panels/flood/index.tsx index 2fc9d36..597564d 100644 --- a/client/src/components/panels/flood/index.tsx +++ b/client/src/components/panels/flood/index.tsx @@ -6,11 +6,12 @@ import { Skeleton } from "@/components/ui/skeleton"; import useDatasetsBySubTopic from "@/hooks/use-datasets-by-sub-topic"; const FloodPanel = () => { - const { data, isLoading } = useDatasetsBySubTopic("flood", "sub_topic.name:desc,name", [ - "name", - "params_config", - "download_link", - ]); + const { data, isLoading } = useDatasetsBySubTopic( + "flood", + "sub_topic.name:desc,name", + ["name", "params_config", "download_link"], + true, + ); return (
diff --git a/client/src/components/panels/hydrometeorological/index.tsx b/client/src/components/panels/hydrometeorological/index.tsx index 163fd7a..b57d1c1 100644 --- a/client/src/components/panels/hydrometeorological/index.tsx +++ b/client/src/components/panels/hydrometeorological/index.tsx @@ -11,6 +11,7 @@ const HydrometeorologicalPanel = () => { "hydrometeorological", "sub_topic.name:desc,name", ["name", "params_config", "download_link"], + true, ); return ( diff --git a/client/src/components/ui/dialog.tsx b/client/src/components/ui/dialog.tsx index b12bdb8..753c255 100644 --- a/client/src/components/ui/dialog.tsx +++ b/client/src/components/ui/dialog.tsx @@ -39,12 +39,12 @@ const DialogContent = React.forwardRef< - {children} +
{children}
+ + + + + + Download dataset + + )} {!!metadata && ( - - - + + + + + + + + More info + + diff --git a/client/src/components/panels/contextual-layers/item.tsx b/client/src/components/panels/contextual-layers/item.tsx index 9642f50..53b4fc3 100644 --- a/client/src/components/panels/contextual-layers/item.tsx +++ b/client/src/components/panels/contextual-layers/item.tsx @@ -6,8 +6,8 @@ import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import useMapLayers from "@/hooks/use-map-layers"; -import { cn } from "@/lib/utils"; import DownloadIcon from "@/svgs/download.svg"; import QuestionMarkIcon from "@/svgs/question-mark.svg"; import { Dataset, Layer, MetadataItemComponent } from "@/types/generated/strapi.schemas"; @@ -35,40 +35,46 @@ const Item = ({ name, layers }: ItemProps) => { {layer.name}
- + {!!layer.downloadLink && ( + + + + + + Download dataset + + + )} {!!layer.metadata && ( - - - + + + + + + + + More info + + diff --git a/client/src/components/ui/tooltip.tsx b/client/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..08ff54b --- /dev/null +++ b/client/src/components/ui/tooltip.tsx @@ -0,0 +1,30 @@ +"use client"; + +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/client/yarn.lock b/client/yarn.lock index 4047941..8af6b56 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -3520,9 +3520,9 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-tooltip@npm:1.1.3": - version: 1.1.3 - resolution: "@radix-ui/react-tooltip@npm:1.1.3" +"@radix-ui/react-tooltip@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-tooltip@npm:1.1.4" dependencies: "@radix-ui/primitive": "npm:1.1.0" "@radix-ui/react-compose-refs": "npm:1.1.0" @@ -3546,7 +3546,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/388f2b74277dc8ac39ef6218e61f5cbebdc9ff5d03a8759bbd9d234561f43fab2771c4537c2e0faaaa19976d5b4cf7eb08112a493dc119e8abc45cbe7a416c97 + checksum: 10c0/721cfb0bf34e74af5a58d89a73e087522517b9502fb7ae9d1dc99137d4952f2bfd1696001e17aa83dfb533c39b4333030149562ebfe62d31238a1a2995bc6bd6 languageName: node linkType: hard @@ -5618,7 +5618,7 @@ __metadata: "@radix-ui/react-slot": "npm:1.1.0" "@radix-ui/react-switch": "npm:1.1.1" "@radix-ui/react-tabs": "npm:1.1.1" - "@radix-ui/react-tooltip": "npm:1.1.3" + "@radix-ui/react-tooltip": "npm:1.1.4" "@svgr/webpack": "npm:8.1.0" "@t3-oss/env-nextjs": "npm:0.11.1" "@tanstack/eslint-plugin-query": "npm:5.59.7" From c94dc0b62e2658f5ef56e25ff867d6fe4f20753c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Prod=27homme?= Date: Wed, 20 Nov 2024 14:49:43 +0100 Subject: [PATCH 3/3] refactor(client): Separate dataset toggle from other icons --- client/src/components/dataset-card/index.tsx | 5 ++++- client/src/components/panels/contextual-layers/item.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/components/dataset-card/index.tsx b/client/src/components/dataset-card/index.tsx index 88fcd91..f811411 100644 --- a/client/src/components/dataset-card/index.tsx +++ b/client/src/components/dataset-card/index.tsx @@ -224,7 +224,7 @@ const DatasetCard = ({ id, name, defaultLayerId, layers, metadata }: DatasetCard -
+
{!!selectedLayer?.attributes!.download_link && ( @@ -270,6 +270,9 @@ const DatasetCard = ({ id, name, defaultLayerId, layers, metadata }: DatasetCard
)} + {(!!selectedLayer?.attributes!.download_link || !!metadata) && ( +
+ )} { -
+
{!!layer.downloadLink && ( @@ -80,6 +80,9 @@ const Item = ({ name, layers }: ItemProps) => {
)} + {(!!layer.downloadLink || !!layer.metadata) && ( +
+ )} id === layer.id) !== -1}