Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit 6becb13

Browse files
ac-jorellanafCito
andauthored
Quick implementation of DIS features (#247)
* Implemented new paths, mocks, etc. for the DIS data Fixed mocks not working with newest models. * Applied most suggestions * Use a map to merge the file info --------- Co-authored-by: Christoph Zwerschke <[email protected]>
1 parent c7a1ebd commit 6becb13

File tree

10 files changed

+128
-32
lines changed

10 files changed

+128
-32
lines changed

.devcontainer/.data_portal_ui.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ host: 0.0.0.0
33
port: 8080
44
mass_url: "api/mass"
55
metldata_url: "api/metldata"
6+
dis_url: "api/dins"
67
ars_url: "api/ars"
78
auth_url: "api/auth"
89
wps_url: "api/wps"

configure_build_serve/run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Config(BaseSettings):
5252
ribbon_text: str = "Development v$v"
5353
mass_url: str = "/api/mass"
5454
metldata_url: str = "/api/metldata"
55+
dis_url: str = "/api/dins"
5556
ars_url: str = "/api/ars"
5657
auth_url: str = "/api/auth"
5758
wps_url: str = "/api/wps"

src/api/browse.ts

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ import {
2020
MetadataSummaryModel,
2121
} from "../models/dataset";
2222
import { FacetFilterModel } from "../models/facets";
23-
import { MASS_URL, METLDATA_URL, fetchJson } from "../utils/utils";
23+
import { DIS_URL, MASS_URL, METLDATA_URL, fetchJson } from "../utils/utils";
2424
import { showMessage } from "../components/messages/usage";
25+
import { DatasetInformationFileSummaryModel } from "../models/files";
2526

2627
const showFetchDataError = () => {
2728
showMessage({
@@ -30,15 +31,6 @@ const showFetchDataError = () => {
3031
});
3132
};
3233

33-
type getDatasetsSearchRespType = (
34-
callbackFunc: (hits: SearchResponseModel) => void,
35-
filterQuery: FacetFilterModel[],
36-
searchKeyword: string,
37-
skip: number,
38-
limit: number,
39-
documentType: string
40-
) => void;
41-
4234
/**
4335
* Async function to retrieve the search results from API, calls the callbackFunc
4436
* function with search results, returns nothing.
@@ -50,7 +42,7 @@ type getDatasetsSearchRespType = (
5042
* @param documentType - String representing the document type to search. Default: "Dataset".
5143
* @returns Nothing
5244
*/
53-
export const querySearchService: getDatasetsSearchRespType = async (
45+
export const querySearchService = async (
5446
callbackFunc: (hits: SearchResponseModel) => void,
5547
filterQuery: FacetFilterModel[],
5648
searchKeyword = "",
@@ -87,21 +79,16 @@ export const querySearchService: getDatasetsSearchRespType = async (
8779
}
8880
};
8981

90-
type getDatasetDetailsType = (
91-
datasetAccession: string,
92-
callbackFunc: (dataset: DatasetEmbeddedModel) => void
93-
) => void;
94-
9582
/**
9683
* Async function to retrieve the details of specified dataset from API,
9784
* calls the callbackFunc function with the response data, returns nothing.
9885
* @param datasetAccession - ID of the dataset of interest.
9986
* @param callbackFunc - Function used to process response data.
10087
* @returns Nothing
10188
*/
102-
export const getDatasetDetails: getDatasetDetailsType = async (
103-
datasetAccession,
104-
callbackFunc
89+
export const getDatasetDetails = async (
90+
datasetAccession: string,
91+
callbackFunc: (dataset: DatasetEmbeddedModel) => void
10592
) => {
10693
let url = new URL(
10794
`artifacts/embedded_public/classes/EmbeddedDataset/resources/${datasetAccession}`,
@@ -117,21 +104,16 @@ export const getDatasetDetails: getDatasetDetailsType = async (
117104
}
118105
};
119106

120-
type getDatasetSummaryType = (
121-
datasetAccession: string,
122-
callbackFunc: (dataset: DatasetDetailsSummaryModel) => void
123-
) => void;
124-
125107
/**
126108
* Async function to retrieve the summary of specified dataset from API,
127109
* calls the callbackFunc function with the response data, returns nothing.
128110
* @param datasetAccession - ID of the dataset of interest.
129111
* @param callbackFunc - Function used to process response data.
130112
* @returns Nothing
131113
*/
132-
export const getDatasetSummary: getDatasetSummaryType = async (
133-
datasetAccession,
134-
callbackFunc
114+
export const getDatasetSummary = async (
115+
datasetAccession: string,
116+
callbackFunc: (dataset: DatasetDetailsSummaryModel) => void
135117
) => {
136118
const url = new URL(
137119
`artifacts/stats_public/classes/DatasetStats/resources/${datasetAccession}`,
@@ -147,6 +129,28 @@ export const getDatasetSummary: getDatasetSummaryType = async (
147129
}
148130
};
149131

132+
/**
133+
* Async function to retrieve the summary of specified dataset's files from API,
134+
* calls the callbackFunc function with the response data, returns nothing.
135+
* @param datasetAccession - ID of the dataset of interest.
136+
* @param callbackFunc - Function used to process response data.
137+
* @returns Nothing
138+
*/
139+
export const getDatasetFiles = async (
140+
datasetAccession: string,
141+
callbackFunc: (dataset: DatasetInformationFileSummaryModel) => void
142+
) => {
143+
const url = new URL(`dataset_information/${datasetAccession}`, DIS_URL);
144+
try {
145+
const response = await fetchJson(url);
146+
const data = await response.json();
147+
callbackFunc(data);
148+
} catch (error) {
149+
showFetchDataError();
150+
console.error(error);
151+
}
152+
};
153+
150154
type getMetadataSummaryType = (
151155
callbackFunc: (summary: MetadataSummaryModel) => void
152156
) => void;

src/components/browse/singleDatasetView/singleDatasetView.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2121
import { useEffect, useState } from "react";
2222
import { Button, Col, Row, Spinner } from "react-bootstrap";
2323
import { useLocation, useNavigate, useParams } from "react-router-dom";
24-
import { getDatasetDetails } from "../../../api/browse";
24+
import { getDatasetDetails, getDatasetFiles } from "../../../api/browse";
2525
import { DatasetEmbeddedModel } from "../../../models/dataset";
2626
import DataRequestFormModal from "../../../utils/dataRequestFormModal";
2727
import SingleDatasetViewAccordion from "./singleDatasetViewAccordion/singleDatasetViewAccordion";
2828
import SingleDatasetViewSummary from "./singleDatasetViewSummary/singleDatasetViewSummary";
2929
import SingleDatasetViewTabs from "./singleDatasetViewTabs/singleDatasetViewTabs";
3030
import RequestAccessButton from "../../../utils/requestAccessButton";
31+
import { DatasetInformationFileSummaryModel } from "../../../models/files";
3132

3233
/** Single dataset details page */
3334
const SingleDatasetView = () => {
@@ -44,12 +45,16 @@ const SingleDatasetView = () => {
4445
const [details, setDetails] = useState<
4546
DatasetEmbeddedModel | null | undefined
4647
>(undefined);
48+
const [datasetFiles, setDatasetFiles] = useState<
49+
DatasetInformationFileSummaryModel | null | undefined
50+
>(undefined);
4751

4852
useEffect(() => {
4953
const getDetails = (datasetAccession: string) => {
5054
if (!queried) {
5155
setQueried(true);
5256
getDatasetDetails(datasetAccession, setDetails);
57+
getDatasetFiles(datasetAccession, setDatasetFiles);
5358
}
5459
};
5560
if (!queried) {
@@ -119,7 +124,17 @@ const SingleDatasetView = () => {
119124
/>
120125
<SingleDatasetViewSummary details={details} />
121126
<SingleDatasetViewTabs details={details} />
122-
<SingleDatasetViewAccordion details={details} />
127+
<SingleDatasetViewAccordion
128+
details={details}
129+
files={
130+
datasetFiles
131+
? datasetFiles
132+
: {
133+
accession: "",
134+
file_information: [],
135+
}
136+
}
137+
/>
123138
</>
124139
)}
125140
</div>

src/components/browse/singleDatasetView/singleDatasetViewAccordion/singleDatasetViewAccordion.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import { FilesTable } from "./tables/filesTable";
2020
import { SamplesTable } from "./tables/samplesTable";
2121
import SortButton, { SDSVTableDefinition } from "../../../../utils/sortButton";
2222
import { parseBytes } from "../../../../utils/utils";
23+
import { DatasetInformationFileSummaryModel } from "../../../../models/files";
2324

2425
interface SingleDatasetViewAccordionProps {
2526
details: DatasetEmbeddedModel;
27+
files: DatasetInformationFileSummaryModel;
2628
}
2729

2830
/** Section at the end of dataset details page consisting of three collapsible summary tables. */
@@ -33,7 +35,18 @@ const SingleDatasetViewAccordion = (props: SingleDatasetViewAccordionProps) => {
3335
const files = (props.details as any)[key];
3436
const file_category =
3537
key.charAt(0).toUpperCase() + key.slice(1, -1).replaceAll("_", " ");
36-
return files.map((file: any) => ({ ...file, file_category }));
38+
const fileInfoMap = new Map();
39+
props.files.file_information.forEach((fileInfo) =>
40+
fileInfoMap.set(fileInfo.accession, fileInfo)
41+
);
42+
return files.map((file: any) => {
43+
const fileInfo = fileInfoMap.get(file.accession) || {
44+
size: 0,
45+
sha256_hash: "",
46+
storage_alias: "",
47+
};
48+
return { ...file, ...fileInfo, file_category };
49+
});
3750
});
3851

3952
let Tables: SDSVTableDefinition[] = [

src/components/browse/singleDatasetView/singleDatasetViewAccordion/tables/filesTable.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// limitations under the License.
1515

1616
import { useState } from "react";
17-
import { transposeTableForHTML } from "../../../../../utils/utils";
17+
import { parseBytes, transposeTableForHTML } from "../../../../../utils/utils";
1818
import {
1919
SDSVTableDefinition,
2020
TableFields,
@@ -67,16 +67,37 @@ export const FilesTable = (props: FilesTableProps) => {
6767
data: allFiles.map((x) => x.file_category),
6868
cssClasses: "",
6969
},
70+
{
71+
header: "File Size",
72+
data: allFiles.map((x) => parseBytes(x.size)),
73+
cssClasses: "",
74+
},
75+
{
76+
header: "File Location",
77+
data: allFiles.map((x) => x.storage_alias),
78+
cssClasses: "",
79+
},
80+
{
81+
header: "File Hash",
82+
data: allFiles.map((x) => x.sha256_hash),
83+
cssClasses: "",
84+
},
7085
];
7186

7287
const [sortedData, setSortedData] = useState<any>(
7388
transposeTableForHTML(filesTable.map((x) => x.data))
7489
);
7590

91+
var totalSize = allFiles.reduce((a, x) => a + x.size, 0);
92+
7693
const filesTableDef: SDSVTableDefinition = {
7794
table: filesTable,
7895
buttonText: allFiles
79-
? "File Summary (" + allFiles.length + " files)"
96+
? "File Summary (" +
97+
allFiles.length +
98+
" files: " +
99+
parseBytes(totalSize) +
100+
")"
80101
: "File Summary (0 files)",
81102
sortDefinition: sortDefinition,
82103
setSortDefinition: setSortDefinition,

src/mocks/data.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ export const searchResults = {
376376
count: 25, // just to test the paginator
377377
hits: [
378378
{
379+
id_: "GHGAD588887987",
379380
content: {
380381
accession: "GHGAD588887987",
381382
ega_accession: "EGAD588887987",
@@ -386,6 +387,7 @@ export const searchResults = {
386387
},
387388
},
388389
{
390+
id_: "GHGAD588887988",
389391
content: {
390392
accession: "GHGAD588887988",
391393
ega_accession: "EGAD588887988",
@@ -396,6 +398,7 @@ export const searchResults = {
396398
},
397399
},
398400
{
401+
id_: "GHGAD588887989",
399402
content: {
400403
accession: "GHGAD588887989",
401404
ega_accession: "EGAD588887989",
@@ -407,3 +410,13 @@ export const searchResults = {
407410
},
408411
],
409412
};
413+
414+
export const filesSummary = {
415+
accession: "GHGAD588887988",
416+
file_information: [{
417+
accession: "GHGASF956121331",
418+
sha256_hash: "58b2e5a09936322db4ab1b921847d0f3b83027e0255cd24d7e58c420845286dc",
419+
size: 123456789,
420+
storage_alias: "Tübingen"
421+
}]
422+
}

src/mocks/responses.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
workPackageToken,
2323
searchResults,
2424
allIVAs,
25+
filesSummary,
2526
} from "./data";
2627

2728
// Responses to be returned for various endpoints.
@@ -119,6 +120,9 @@ export const responses = {
119120
// Get summary data from entire metadata database
120121
"GET /api/metldata/stats": metadataSummary,
121122

123+
// Get summary data from all files in a dataset
124+
"GET /api/dins/dataset_information/*": filesSummary,
125+
122126
// Metadata Search Service
123127
"GET /api/mass/search*": {
124128
facets: searchResults.facets,

src/models/files.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2021 - 2024 Universität Tübingen, DKFZ and EMBL
2+
// for the German Human Genome-Phenome Archive (GHGA)
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
export interface DatasetInformationFileSummaryModel {
16+
accession: string;
17+
file_information: {
18+
accession: string;
19+
sha256_hash: string;
20+
size: number;
21+
storage_alias: string;
22+
}[];
23+
}

src/utils/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const AUTH_URL = getConfiguredUrl("AUTH_URL");
3939
export const ARS_URL = getConfiguredUrl("ARS_URL");
4040
export const MASS_URL = getConfiguredUrl("MASS_URL");
4141
export const METLDATA_URL = getConfiguredUrl("METLDATA_URL");
42+
export const DIS_URL = getConfiguredUrl("DIS_URL");
4243
export const WPS_URL = getConfiguredUrl("WPS_URL");
4344

4445
export const OIDC_AUTHORITY_URL = getConfiguredUrl("OIDC_AUTHORITY_URL");

0 commit comments

Comments
 (0)