diff --git a/frontend/src/components/datasets/DatasetDetails.tsx b/frontend/src/components/datasets/DatasetDetails.tsx index 206d573d3..932fbd673 100644 --- a/frontend/src/components/datasets/DatasetDetails.tsx +++ b/frontend/src/components/datasets/DatasetDetails.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Box, Typography } from "@mui/material"; import { parseDate } from "../../utils/common"; import { StackedList } from "../util/StackedList"; -import { Dataset } from "../../types/data"; +import { DatasetOut as Dataset } from "../../openapi/v2"; type DatasetAboutProps = { myRole?: string; @@ -13,15 +13,31 @@ export function DatasetDetails(props: DatasetAboutProps) { const { myRole } = props; const { id, created, modified, creator, status, downloads } = props.details; - const details = new Map(); - details.set("Owner", `${creator.first_name} ${creator.last_name}`); - details.set("Created on", parseDate(created)); - details.set("Updated on", parseDate(modified)); - details.set("Status", status); - details.set("Dataset id", id); - details.set("Downloads", downloads); + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); + details.set("Owner", { value: `${creator.first_name} ${creator.last_name}` }); + details.set("Created", { + value: parseDate(created), + info: "Date and time of dataset creation", + }); + details.set("Updated", { + value: parseDate(modified), + info: "Date and time of dataset modification", + }); + details.set("Status", { value: status, info: "Public or private dataset" }); + details.set("Dataset identifier", { value: id }); + details.set("Downloads", { + value: downloads, + info: "Number of downloads", + }); - if (myRole) details.set("My Role", myRole ? myRole.toUpperCase() : ""); + if (myRole) + details.set("My role", { + value: myRole ? myRole.toUpperCase() : "", + info: "Your role on the dataset. E.g. Owner, Editor, Uploader, Viewer.", + }); return ( diff --git a/frontend/src/components/files/FileDetails.tsx b/frontend/src/components/files/FileDetails.tsx index b92181cd5..4fbdf3937 100644 --- a/frontend/src/components/files/FileDetails.tsx +++ b/frontend/src/components/files/FileDetails.tsx @@ -23,35 +23,62 @@ export function FileDetails(props: FileAboutProps) { storage_type, } = props.fileSummary; - const details = new Map(); - details.set("Size", prettyBytes(bytes)); - details.set("Content type", content_type.content_type); - details.set("Updated on", parseDate(created)); - details.set("Uploaded as", name); - details.set("Uploaded by", `${creator.first_name} ${creator.last_name}`); + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); + details.set("Size", { value: prettyBytes(bytes) }); + details.set("Content type", { value: content_type.content_type }); + details.set("Updated", { + value: parseDate(created), + info: "Latest date and time of the file being updated", + }); + details.set("Uploaded", { value: name, info: "Name of the file" }); + details.set("Uploader", { + value: `${creator.first_name} ${creator.last_name}`, + }); switch (storage_type) { case "minio": { - details.set("Storage location", "Database"); + details.set("Storage location", { + value: "Local object store", + info: "Data stored in the MinIO instance", + }); break; } case "local": { - details.set("Storage location", "Local file system"); + details.set("Storage location", { + value: "Local file system", + info: "Data stored in the local file system", + }); break; } case "remote": { - details.set("Storage location", "Remote URL"); + details.set("Storage location", { + value: "Remote URL", + info: "Data stored in a remote location", + }); break; } default: { - details.set("Storage location", `${storage_type}`); + details.set("Storage location", { + value: `${storage_type}`, + info: `Data stored in ${storage_type}`, + }); break; } } - details.set("File id", id); - details.set("Downloads", downloads); + details.set("File identifier", { value: id }); + details.set("Downloads", { + value: downloads, + info: "Number of downloads", + }); - if (myRole) details.set("My Role", myRole ? myRole.toUpperCase() : ""); + if (myRole) + details.set("My role", { + value: myRole ? myRole.toUpperCase() : "", + info: "Your role on the file. E.g. Owner, Editor, Uploader, Viewer.", + }); return ( diff --git a/frontend/src/components/files/FileHistory.tsx b/frontend/src/components/files/FileHistory.tsx index 9d93291b3..dbcf98788 100644 --- a/frontend/src/components/files/FileHistory.tsx +++ b/frontend/src/components/files/FileHistory.tsx @@ -39,25 +39,33 @@ export function FileHistory(props: FileHistoryAboutProps) { } }, [selectedVersionNum]); - const details = new Map(); + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); + if ( selectedFileVersionDetail !== null && selectedFileVersionDetail !== undefined ) { - details.set( - "Size", - selectedFileVersionDetail.bytes + details.set("Size", { + value: selectedFileVersionDetail.bytes ? prettyBytes(selectedFileVersionDetail.bytes) - : "NA" - ); - details.set("Content type", contentType ?? "NA"); - details.set("Updated on", parseDate(selectedFileVersionDetail.created)); - details.set("Uploaded as", name ?? "NA"); - details.set( - "Uploaded by", - `${selectedFileVersionDetail.creator.first_name} ${selectedFileVersionDetail.creator.last_name}` - ); - details.set("File id", selectedFileVersionDetail.file_id); + : "NA", + }); + details.set("Content type", { value: contentType ?? "NA" }); + details.set("Updated on", { + value: parseDate(selectedFileVersionDetail.created), + info: "Latest date and time of the file being updated", + }); + details.set("Uploaded as", { + value: name ?? "NA", + info: "Name of the file", + }); + details.set("Uploaded by", { + value: `${selectedFileVersionDetail.creator.first_name} ${selectedFileVersionDetail.creator.last_name}`, + }); + details.set("File id", { value: selectedFileVersionDetail.file_id }); } return ( diff --git a/frontend/src/components/listeners/ListenerInfoDetails.tsx b/frontend/src/components/listeners/ListenerInfoDetails.tsx index 762f4bf31..3664bfd35 100644 --- a/frontend/src/components/listeners/ListenerInfoDetails.tsx +++ b/frontend/src/components/listeners/ListenerInfoDetails.tsx @@ -17,66 +17,83 @@ export function ListenerInfoDetails(props: ListenerAboutProps) { defaultExpanded ? defaultExpanded : false ); - const handleChange = - (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { - setExpanded(isExpanded ? panel : false); - }; - - const details = new Map(); - details.set("Last Alive", parseDate(listener.lastAlive ?? "")); - details.set("Last Modified", parseDate(listener.modified ?? "")); + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); + + details.set("Last Alive", { + value: parseDate(listener.lastAlive ?? ""), + info: "Last time the listener was up" + " running", + }); + details.set("Last Modified", { + value: parseDate(listener.modified ?? ""), + info: "Last time the listener was modified", + }); if (listener.properties) { - details.set("Maturity", listener.properties.maturity ?? ""); + details.set("Maturity", { + value: listener.properties.maturity ?? "", + info: "Stage of the listener. e.g. alpha, beta, stable", + }); if ( listener.properties.contributors && listener.properties.contributors.length > 0 ) { - details.set("Contributors", listener.properties.contributors.join(", ")); + details.set("Contributors", { + value: listener.properties.contributors.join(", "), + }); } if ( listener.properties.external_services && listener.properties.external_services.length > 0 ) { - details.set( - "External Services", - listener.properties.external_services.join(", ") - ); + details.set("External Services", { + value: listener.properties.external_services.join(", "), + info: "External services used by the listener", + }); } if ( listener.properties.categories && listener.properties.categories.length > 0 ) { - details.set("Categories", listener.properties.categories.join(", ")); + details.set("Categories", { + value: listener.properties.categories.join(", "), + info: "Categories of the" + " listener", + }); } if (listener.properties.bibtex && listener.properties.bibtex.length > 0) { - details.set( - "Bibtex", - listener.properties.bibtex.join(", ") !== "" - ? listener.properties.bibtex.join(", ") - : "Not Available" - ); + details.set("Bibtex", { + value: + listener.properties.bibtex.join(", ") !== "" + ? listener.properties.bibtex.join(", ") + : "Not Available", + info: "Bibtex format of citation of the listener", + }); } if ( listener.properties.default_labels && listener.properties.default_labels.length > 0 ) { - details.set( - "Default Labels", - listener.properties.default_labels.join(", ") - ); + details.set("Default Labels", { + value: listener.properties.default_labels.join(", "), + info: "Labels of the listener", + }); } if ( listener.properties.libraries && listener.properties.libraries.length > 0 ) { - details.set("Libraries", listener.properties.libraries.join(", ")); + details.set("Libraries", { + value: listener.properties.libraries.join(", "), + info: "Libraries used by the listener", + }); } if ( @@ -84,10 +101,9 @@ export function ListenerInfoDetails(props: ListenerAboutProps) { Object.keys(listener.properties.process).length > 0 ) { Object.keys(listener.properties.process).forEach((key) => { - details.set( - `Process ${key} by`, - listener.properties.process[key].join(", ") - ); + details.set(`Process ${key} by`, { + value: listener.properties.process[key].join(", "), + }); }); } @@ -97,7 +113,10 @@ export function ListenerInfoDetails(props: ListenerAboutProps) { ) { listener.properties.contexts.forEach((context) => { Object.keys(context).forEach((key) => { - details.set(`Context: ${key}`, context[key]); + details.set(`Context: ${key}`, { + value: context[key], + info: "Context of the listener", + }); }); }); } @@ -108,7 +127,10 @@ export function ListenerInfoDetails(props: ListenerAboutProps) { ) { listener.properties.repository.forEach((repo) => { Object.keys(repo).forEach((key) => { - details.set(key, repo[key] !== "" ? repo[key] : "Not Available"); + details.set(key, { + value: repo[key] !== "" ? repo[key] : "Not Available", + info: "Code repository of the listener", + }); }); }); } diff --git a/frontend/src/components/util/StackedList.tsx b/frontend/src/components/util/StackedList.tsx index c00330342..bcb96286e 100644 --- a/frontend/src/components/util/StackedList.tsx +++ b/frontend/src/components/util/StackedList.tsx @@ -1,25 +1,29 @@ import React from "react"; -import { Box, Stack, Typography } from "@mui/material"; +import { Box, Stack, Tooltip, Typography } from "@mui/material"; +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; type StackedListProps = { - keyValues: Map; + keyValues: Map; }; export function StackedList(props: StackedListProps) { const { keyValues } = props; - const entries: Array = []; - // forEach expects value first and then key - keyValues.forEach((value, key) => { - entries.push( - - {value} - - {key} - - - ); - }); + const entries = Array.from(keyValues, ([key, { value, info }]) => ( + + {value} + + + + {key} + + {info && ( + + )} + + + + )); return {entries}; } diff --git a/frontend/src/components/visualizations/VisualizationDataDetail.tsx b/frontend/src/components/visualizations/VisualizationDataDetail.tsx index e0752e2df..c4ccf33a5 100644 --- a/frontend/src/components/visualizations/VisualizationDataDetail.tsx +++ b/frontend/src/components/visualizations/VisualizationDataDetail.tsx @@ -12,22 +12,33 @@ type FileAboutProps = { export function VisualizationDataDetail(props: FileAboutProps) { const { visualizationDataItem } = props; - const details = new Map(); - details.set("Size", prettyBytes(visualizationDataItem.bytes ?? 0)); - details.set( - "Content type", - visualizationDataItem.content_type + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); + + details.set("Size", { value: prettyBytes(visualizationDataItem.bytes ?? 0) }); + details.set("Content type", { + value: visualizationDataItem.content_type ? visualizationDataItem.content_type.content_type - : "NA" - ); - details.set("Updated on", parseDate(visualizationDataItem.created)); - details.set("Uploaded as", visualizationDataItem.name); - details.set( - "Uploaded by", - `${visualizationDataItem.creator.first_name} ${visualizationDataItem.creator.last_name}` - ); - details.set("Visualization id", visualizationDataItem.id); - details.set("Descriptions", visualizationDataItem.description); + : "NA", + }); + details.set("Updated on", { + value: parseDate(visualizationDataItem.created), + info: "Latest date and time of the file being updated", + }); + details.set("Uploaded as", { + value: visualizationDataItem.name, + info: "Name of the visualization extractor", + }); + details.set("Uploaded by", { + value: `${visualizationDataItem.creator.first_name} ${visualizationDataItem.creator.last_name}`, + }); + details.set("Visualization id", { value: visualizationDataItem.id }); + details.set("Descriptions", { + value: visualizationDataItem.description, + info: "Description of the visualization", + }); return ( <> diff --git a/frontend/src/components/visualizations/VisualizationParamDetail.tsx b/frontend/src/components/visualizations/VisualizationParamDetail.tsx index 18311838c..e278de46a 100644 --- a/frontend/src/components/visualizations/VisualizationParamDetail.tsx +++ b/frontend/src/components/visualizations/VisualizationParamDetail.tsx @@ -10,10 +10,13 @@ type FileAboutProps = { export function VisualizationParamDetail(props: FileAboutProps) { const { visConfigEntry } = props; - const details = new Map(); + const details = new Map< + string, + { value: string | undefined; info?: string } + >(); for (const key in visConfigEntry.parameters) { - details.set(key, visConfigEntry.parameters[key]); + details.set(key, { value: visConfigEntry.parameters[key] }); } return (