Skip to content

Commit

Permalink
feat(client): Display dataset metadata in dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
clementprdhomme committed Nov 20, 2024
1 parent c738faa commit ce83b06
Show file tree
Hide file tree
Showing 14 changed files with 1,012 additions and 24 deletions.
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
24 changes: 22 additions & 2 deletions client/src/components/dataset-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 {
Expand All @@ -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(
Expand Down Expand Up @@ -235,6 +239,22 @@ const DatasetCard = ({ id, name, defaultLayerId, layers }: DatasetCardProps) =>
</Link>
</Button>
)}
{!!metadata && (
<Dialog>
<DialogTrigger asChild>
<Button variant="ghost" size="icon-sm" className="group/info">
<span className="sr-only">Information</span>
<QuestionMarkIcon
className="!size-4 transition-colors group-hover/info:text-casper-blue-300"
aria-hidden
/>
</Button>
</DialogTrigger>
<DialogContent>
<DatasetMetadata name={name} metadata={metadata} />
</DialogContent>
</Dialog>
)}
<Switch
id={`dataset-${id}-toggle`}
checked={isDatasetActive}
Expand Down
93 changes: 93 additions & 0 deletions client/src/components/dataset-metadata/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import Link from "next/link";

import Markdown from "@/components/markdown";
import { DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { MetadataItemComponent } from "@/types/generated/strapi.schemas";

interface DatasetMetadataProps {
name: string;
metadata: MetadataItemComponent;
}

const DatasetMetadata = ({ name, metadata }: DatasetMetadataProps) => {
return (
<>
<DialogHeader>
<DialogTitle>{name}</DialogTitle>
</DialogHeader>
<dl className="mt-8 flex flex-col gap-2 text-xs">
{!!metadata.full_name && (
<div>
<dt className="font-bold">Full name</dt>
<dd>{metadata.full_name}</dd>
</div>
)}
{!!metadata.source && (
<div>
<dt className="font-bold">Source</dt>
<dd>{metadata.source}</dd>
</div>
)}
{!!metadata.website && (
<div>
<dt className="font-bold">Website</dt>
<dd>
<Link
href={metadata.website}
target="_blank"
rel="noopener noreferrer"
className="break-all underline"
>
{metadata.website}
</Link>
</dd>
</div>
)}
{!!metadata.description && (
<div>
<dt className="font-bold">Description</dt>
<dd>{metadata.description}</dd>
</div>
)}
{!!metadata.main_applications && (
<div>
<dt className="font-bold">Main applications</dt>
<dd>
<Markdown>{metadata.main_applications}</Markdown>
</dd>
</div>
)}
{!!metadata.temporal_resolution && (
<div>
<dt className="font-bold">Temporal resolution</dt>
<dd>
<Markdown>{metadata.temporal_resolution}</Markdown>
</dd>
</div>
)}
{!!metadata.temporal_coverage && (
<div>
<dt className="font-bold">Temporal coverage</dt>
<dd>
<Markdown>{metadata.temporal_coverage}</Markdown>
</dd>
</div>
)}
{!!metadata.spatial_resolution && (
<div>
<dt className="font-bold">Spatial resolution</dt>
<dd>{metadata.spatial_resolution}</dd>
</div>
)}
{!!metadata.units && (
<div>
<dt className="font-bold">Units</dt>
<dd>{metadata.units}</dd>
</div>
)}
</dl>
</>
);
};

export default DatasetMetadata;
32 changes: 32 additions & 0 deletions client/src/components/markdown/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ReactMarkdown
allowedElements={["ul", "ol", "li", "b", "strong", "em", "i", "a", "br", "p"]}
components={{
ul: ({ children }) => <ul className="list-inside list-disc">{children}</ul>,
ol: ({ children }) => <ol className="list-inside list-decimal">{children}</ol>,
a: ({ children, href }) => (
<Link
href={href!}
target={href?.startsWith("http") ? "_blank" : undefined}
rel={href?.startsWith("http") ? "noopener noreferrer" : undefined}
className="break-all underline"
>
{children}
</Link>
),
}}
>
{children}
</ReactMarkdown>
);
};

export default Markdown;
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const NavigationDesktop = () => {
<MapPinIcon aria-hidden />
</Button>
</DialogTrigger>
<DialogContent className="gap-0">
<DialogContent>
<LocationPanel onExit={onExitLocationDialog} />
</DialogContent>
</Dialog>
Expand Down
11 changes: 7 additions & 4 deletions client/src/components/panels/contextual-layers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
Expand Down Expand Up @@ -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,
}))}
/>
))}
Expand Down
29 changes: 27 additions & 2 deletions client/src/components/panels/contextual-layers/item.tsx
Original file line number Diff line number Diff line change
@@ -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) => {
Expand Down Expand Up @@ -49,6 +58,22 @@ const Item = ({ name, layers }: ItemProps) => {
/>
</Link>
</Button>
{!!layer.metadata && (
<Dialog>
<DialogTrigger asChild>
<Button variant="ghost" size="icon-sm" className="group/info">
<span className="sr-only">Information</span>
<QuestionMarkIcon
className="!size-4 transition-colors group-hover/info:text-casper-blue-300"
aria-hidden
/>
</Button>
</DialogTrigger>
<DialogContent>
<DatasetMetadata name={name} metadata={layer.metadata} />
</DialogContent>
</Dialog>
)}
<Switch
id={`${layer.id}-toggle`}
checked={layersConfiguration.findIndex(({ id }) => id === layer.id) !== -1}
Expand Down
11 changes: 6 additions & 5 deletions client/src/components/panels/drought/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="min-h-screen px-5 py-5 lg:min-h-0 lg:px-10">
Expand Down
11 changes: 6 additions & 5 deletions client/src/components/panels/flood/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="min-h-screen px-5 py-5 lg:min-h-0 lg:px-10">
Expand Down
1 change: 1 addition & 0 deletions client/src/components/panels/hydrometeorological/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const HydrometeorologicalPanel = () => {
"hydrometeorological",
"sub_topic.name:desc,name",
["name", "params_config", "download_link"],
true,
);

return (
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-10 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 bg-rhino-blue-900 px-10 py-12 text-white duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
"fixed left-[50%] top-[50%] z-10 flex max-h-[calc(100vh_-_theme(spacing.10))] w-full max-w-lg translate-x-[-50%] translate-y-[-50%] flex-col gap-4 bg-rhino-blue-900 px-10 py-12 text-white duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
className,
)}
{...props}
>
{children}
<div className="overflow-y-auto">{children}</div>
<DialogPrimitive.Close className="absolute right-0 top-5 translate-x-1/2" asChild>
<Button type="button" variant="yellow" size="icon">
<XMarkIcon aria-hidden className="!size-5 xl:!size-6" />
Expand Down
7 changes: 6 additions & 1 deletion client/src/hooks/use-datasets-by-sub-topic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useGetDatasets } from "@/types/generated/dataset";
import { DatasetLayersDataItem } from "@/types/generated/strapi.schemas";
import { DatasetLayersDataItem, MetadataItemComponent } from "@/types/generated/strapi.schemas";

type DatasetsBySubTopic = {
subTopic: string;
Expand All @@ -8,13 +8,15 @@ type DatasetsBySubTopic = {
name: string;
defaultLayerId: number | undefined;
layers: DatasetLayersDataItem[];
metadata?: MetadataItemComponent;
}[];
};

export default function useDatasetsBySubTopic(
topicSlug: string,
sort = "sub_topic.name,name",
layersFields = ["name"],
includeMetadata = false,
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore-error
Expand All @@ -34,6 +36,7 @@ export default function useDatasetsBySubTopic(
fields: layersFields,
sort: "name",
},
metadata: includeMetadata,
},
filters: {
topic: {
Expand Down Expand Up @@ -62,6 +65,7 @@ export default function useDatasetsBySubTopic(
const dataset = item.attributes!.name;
const defaultLayerId = item.attributes!.default_layer!.data?.id;
const layers = item.attributes!.layers!.data!;
const metadata = item.attributes!.metadata;

if (currentSubTopic === null || currentSubTopic !== subTopic) {
currentSubTopic = subTopic;
Expand All @@ -74,6 +78,7 @@ export default function useDatasetsBySubTopic(
name: dataset,
defaultLayerId,
layers,
...(includeMetadata ? { metadata: metadata ?? undefined } : {}),
});
}

Expand Down
6 changes: 6 additions & 0 deletions client/src/svgs/question-mark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ce83b06

Please sign in to comment.