Skip to content

Commit 4e77612

Browse files
committed
fix: show accurate metadata size on dataset cards and dataset detail page
1 parent 0f8b71d commit 4e77612

File tree

4 files changed

+202
-150
lines changed

4 files changed

+202
-150
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { Box, Typography } from "@mui/material";
2+
import { Colors } from "design/theme";
3+
import React from "react";
4+
5+
type Props = {
6+
dbViewInfo: any;
7+
datasetDocument: any;
8+
};
9+
10+
const MetaDataPanel: React.FC<Props> = ({ dbViewInfo, datasetDocument }) => {
11+
return (
12+
<Box
13+
sx={{
14+
backgroundColor: Colors.white,
15+
borderRadius: "8px",
16+
display: "flex",
17+
flexDirection: "column",
18+
overflow: "hidden",
19+
height: "100%",
20+
minHeight: 0,
21+
}}
22+
>
23+
<Box
24+
sx={{
25+
flex: 1,
26+
minHeight: 0, // <-- for scroller
27+
overflowY: "auto", // <-- keep the scroller here
28+
p: 2,
29+
display: "flex",
30+
flexDirection: "column",
31+
gap: 1,
32+
}}
33+
>
34+
<Box>
35+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
36+
Modalities
37+
</Typography>
38+
<Typography sx={{ color: "text.secondary" }}>
39+
{dbViewInfo?.rows?.[0]?.value?.modality?.join(", ") ?? "N/A"}
40+
</Typography>
41+
</Box>
42+
43+
<Box>
44+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
45+
DOI
46+
</Typography>
47+
<Typography sx={{ color: "text.secondary" }}>
48+
{(() => {
49+
const doi =
50+
datasetDocument?.["dataset_description.json"]?.DatasetDOI ||
51+
datasetDocument?.["dataset_description.json"]?.ReferenceDOI;
52+
53+
if (!doi) return "N/A";
54+
55+
// Normalize into a clickable URL
56+
let url = doi;
57+
if (/^10\./.test(doi)) {
58+
url = `https://doi.org/${doi}`;
59+
} else if (/^doi:/.test(doi)) {
60+
url = `https://doi.org/${doi.replace(/^doi:/, "")}`;
61+
}
62+
63+
return (
64+
<a
65+
href={url}
66+
target="_blank"
67+
rel="noopener noreferrer"
68+
style={{
69+
color: "inherit",
70+
textDecoration: "underline",
71+
}}
72+
>
73+
{url}
74+
</a>
75+
);
76+
})()}
77+
</Typography>
78+
</Box>
79+
80+
<Box>
81+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
82+
Subjects
83+
</Typography>
84+
<Typography sx={{ color: "text.secondary" }}>
85+
{dbViewInfo?.rows?.[0]?.value?.subj?.length ?? "N/A"}
86+
</Typography>
87+
</Box>
88+
<Box>
89+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
90+
License
91+
</Typography>
92+
<Typography sx={{ color: "text.secondary" }}>
93+
{datasetDocument?.["dataset_description.json"]?.License ?? "N/A"}
94+
</Typography>
95+
</Box>
96+
<Box>
97+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
98+
BIDS Version
99+
</Typography>
100+
<Typography sx={{ color: "text.secondary" }}>
101+
{datasetDocument?.["dataset_description.json"]?.BIDSVersion ??
102+
"N/A"}
103+
</Typography>
104+
</Box>
105+
<Box>
106+
<Typography sx={{ color: Colors.darkPurple, fontWeight: "600" }}>
107+
References and Links
108+
</Typography>
109+
<Typography sx={{ color: "text.secondary" }}>
110+
{Array.isArray(
111+
datasetDocument?.["dataset_description.json"]?.ReferencesAndLinks
112+
)
113+
? datasetDocument["dataset_description.json"].ReferencesAndLinks
114+
.length > 0
115+
? datasetDocument[
116+
"dataset_description.json"
117+
].ReferencesAndLinks.join(", ")
118+
: "N/A"
119+
: datasetDocument?.["dataset_description.json"]
120+
?.ReferencesAndLinks ?? "N/A"}
121+
</Typography>
122+
</Box>
123+
</Box>
124+
</Box>
125+
);
126+
};
127+
128+
export default MetaDataPanel;

src/components/DatasetPageCard.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@ import { useNavigate } from "react-router-dom";
1515
import { Row } from "redux/neurojson/types/neurojson.interface";
1616
import RoutesEnum from "types/routes.enum";
1717

18+
const formatSize = (sizeInBytes: number): string => {
19+
if (sizeInBytes < 1024) {
20+
return `${sizeInBytes} Bytes`;
21+
} else if (sizeInBytes < 1024 * 1024) {
22+
return `${(sizeInBytes / 1024).toFixed(1)} KB`;
23+
} else if (sizeInBytes < 1024 * 1024 * 1024) {
24+
return `${(sizeInBytes / (1024 * 1024)).toFixed(2)} MB`;
25+
} else if (sizeInBytes < 1024 * 1024 * 1024 * 1024) {
26+
return `${(sizeInBytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
27+
} else {
28+
return `${(sizeInBytes / (1024 * 1024 * 1024 * 1024)).toFixed(2)} TB`;
29+
}
30+
};
31+
32+
// for showing the size
33+
const jsonBytes = (obj: unknown) =>
34+
obj ? new TextEncoder().encode(JSON.stringify(obj)).length : 0;
35+
1836
interface DatasetPageCardProps {
1937
doc: Row;
2038
index: number;
@@ -32,6 +50,11 @@ const DatasetPageCard: React.FC<DatasetPageCardProps> = ({
3250
}) => {
3351
const navigate = useNavigate();
3452
const datasetIndex = (page - 1) * pageSize + index + 1;
53+
const sizeInBytes = React.useMemo(() => {
54+
const len = (doc as any)?.value?.length; // bytes from backend (full doc)
55+
if (typeof len === "number" && Number.isFinite(len)) return len;
56+
return jsonBytes(doc.value); // fallback: summary object size
57+
}, [doc.value]);
3558
return (
3659
<Grid item xs={12} sm={6} key={doc.id}>
3760
<Card
@@ -133,9 +156,10 @@ const DatasetPageCard: React.FC<DatasetPageCardProps> = ({
133156
<Stack direction="row" spacing={2} alignItems="center">
134157
<Typography variant="body2" color={Colors.textPrimary}>
135158
<strong>Size:</strong>{" "}
136-
{doc.value.length
159+
{/* {doc.value.length
137160
? `${(doc.value.length / 1024 / 1024).toFixed(2)} MB`
138-
: "Unknown"}
161+
: "Unknown"} */}
162+
{formatSize(sizeInBytes)}
139163
</Typography>
140164

141165
{doc.value.info?.DatasetDOI && (

src/pages/DatasetPage.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ const DatasetPage: React.FC = () => {
3939
const totalPages = Math.ceil(limit / pageSize);
4040
const [searchQuery, setSearchQuery] = useState("");
4141

42+
const formatSize = (sizeInBytes: number): string => {
43+
if (sizeInBytes < 1024) {
44+
return `${sizeInBytes} Bytes`;
45+
} else if (sizeInBytes < 1024 * 1024) {
46+
return `${(sizeInBytes / 1024).toFixed(1)} KB`;
47+
} else if (sizeInBytes < 1024 * 1024 * 1024) {
48+
return `${(sizeInBytes / (1024 * 1024)).toFixed(2)} MB`;
49+
} else if (sizeInBytes < 1024 * 1024 * 1024 * 1024) {
50+
return `${(sizeInBytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
51+
} else {
52+
return `${(sizeInBytes / (1024 * 1024 * 1024 * 1024)).toFixed(2)} TB`;
53+
}
54+
};
55+
4256
useEffect(() => {
4357
if (dbName) {
4458
dispatch(fetchDbInfo(dbName.toLowerCase()));
@@ -326,11 +340,12 @@ const DatasetPage: React.FC = () => {
326340
<Grid container spacing={3}>
327341
{filteredData.map((doc: any, index: number) => {
328342
const datasetIndex = (currentPage - 1) * pageSize + index + 1;
343+
329344
return (
330345
<Grid item xs={12} sm={6} key={doc.id}>
331346
<Card
332347
sx={{
333-
position: "relative", // allows absolute positioning of the number
348+
position: "relative", // allows absolute positioning of the number
334349
backgroundColor: Colors.white,
335350
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
336351
height: "100%",

0 commit comments

Comments
 (0)