Skip to content

Commit 2b49367

Browse files
authored
feat: export cohort to biodata catalyst (#4640) (#4653)
Co-authored-by: Fran McDade <18710366+frano-m@users.noreply.github.com>
1 parent 1fc0b45 commit 2b49367

File tree

12 files changed

+335
-23
lines changed

12 files changed

+335
-23
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { JSX } from "react";
2+
import { ComponentProps } from "react";
3+
import { ExportMethod as DXExportMethod } from "@databiosphere/findable-ui/lib/components/Export/components/ExportMethod/exportMethod";
4+
import { useFeatureFlag } from "@databiosphere/findable-ui/lib/hooks/useFeatureFlag/useFeatureFlag";
5+
import { FEATURES } from "app/shared/entities";
6+
7+
/**
8+
* Export method component for platform based export.
9+
* Hidden if the platform based export feature is not enabled (NCPI Export).
10+
* @param props - Export method component props.
11+
* @returns Export method component.
12+
*/
13+
export const ExportMethod = (
14+
props: ComponentProps<typeof DXExportMethod>
15+
): JSX.Element | null => {
16+
const isEnabled = useFeatureFlag(FEATURES.NCPI_EXPORT);
17+
18+
if (!isEnabled) return null;
19+
20+
return <DXExportMethod {...props} />;
21+
};
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { JSX } from "react";
2+
import { BUTTON_PROPS } from "@databiosphere/findable-ui/lib/components/common/Button/constants";
3+
import { useFileManifest } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/useFileManifest";
4+
import { useFileManifestFileCount } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/useFileManifestFileCount";
5+
import { useFileManifestFormat } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/useFileManifestFormat";
6+
import { useRequestFileLocation } from "@databiosphere/findable-ui/lib/hooks/useRequestFileLocation";
7+
import { useRequestManifest } from "@databiosphere/findable-ui/lib/hooks/useRequestManifest/useRequestManifest";
8+
import { FluidPaper } from "@databiosphere/findable-ui/lib/components/common/Paper/components/FluidPaper/fluidPaper";
9+
import { Loading } from "@databiosphere/findable-ui/lib/components/Loading/loading";
10+
import { ExportManifestDownloadFormatForm } from "@databiosphere/findable-ui/lib/components/Export/components/ExportForm/components/ExportManifestDownloadFormatForm/exportManifestDownloadFormatForm";
11+
import { ExportButton } from "@databiosphere/findable-ui/lib/components/Export/components/ExportForm/components/ExportButton/exportButton";
12+
import { ExportForm } from "@databiosphere/findable-ui/lib/components/Export/components/ExportForm/exportForm";
13+
import {
14+
Section,
15+
SectionActions,
16+
SectionContent,
17+
} from "@databiosphere/findable-ui/lib/components/Export/export.styles";
18+
import { Button } from "@mui/material";
19+
import {
20+
REL_ATTRIBUTE,
21+
ANCHOR_TARGET,
22+
} from "@databiosphere/findable-ui/lib/components/Links/common/entities";
23+
import { PAPER_PANEL_STYLE } from "@databiosphere/findable-ui/lib/components/common/Paper/paper";
24+
import { MANIFEST_DOWNLOAD_FORMAT } from "@databiosphere/findable-ui/lib/apis/azul/common/entities";
25+
import { Props } from "./types";
26+
27+
export const ExportToPlatform = ({
28+
buttonLabel,
29+
description,
30+
fileManifestState,
31+
fileSummaryFacetName,
32+
filters,
33+
formFacet,
34+
speciesFacetName,
35+
successTitle,
36+
title,
37+
}: Props): JSX.Element => {
38+
useFileManifest(filters, fileSummaryFacetName);
39+
useFileManifestFileCount(filters, speciesFacetName, fileSummaryFacetName);
40+
41+
const fileManifestFormatState = useFileManifestFormat(
42+
MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB
43+
);
44+
const { fileManifestFormat } = fileManifestFormatState;
45+
46+
const requestManifest = useRequestManifest(fileManifestFormat, formFacet);
47+
const { requestMethod, requestUrl } = requestManifest;
48+
49+
const response = useRequestFileLocation(requestUrl, requestMethod);
50+
const url = "";
51+
52+
return url ? (
53+
<FluidPaper>
54+
<Section>
55+
<SectionContent>
56+
<h3>{successTitle}</h3>
57+
</SectionContent>
58+
<SectionActions>
59+
<Button
60+
{...BUTTON_PROPS.PRIMARY_CONTAINED}
61+
href={url}
62+
rel={REL_ATTRIBUTE.NO_OPENER_NO_REFERRER}
63+
target={ANCHOR_TARGET.BLANK}
64+
>
65+
{buttonLabel}
66+
</Button>
67+
</SectionActions>
68+
</Section>
69+
</FluidPaper>
70+
) : (
71+
<div>
72+
<Loading
73+
loading={response.isLoading}
74+
panelStyle={PAPER_PANEL_STYLE.FLUID}
75+
text="Your link will be ready shortly..."
76+
/>
77+
<FluidPaper>
78+
<Section>
79+
<SectionContent>
80+
<h3>{title}</h3>
81+
<p>{description}</p>
82+
</SectionContent>
83+
<ExportForm
84+
Button={renderButton}
85+
formFacet={formFacet}
86+
isLoading={fileManifestState.isLoading}
87+
onRequestManifest={(): void => response.run()}
88+
>
89+
<ExportManifestDownloadFormatForm
90+
fileManifestFormatState={fileManifestFormatState}
91+
manifestDownloadFormats={[MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB]}
92+
/>
93+
</ExportForm>
94+
</Section>
95+
</FluidPaper>
96+
</div>
97+
);
98+
};
99+
100+
/**
101+
* Build the export button.
102+
* @param props - Button props e.g. "onClick" to request manifest.
103+
* @returns button element.
104+
*/
105+
function renderButton({ ...props }): JSX.Element {
106+
return <ExportButton {...props}>Request Link</ExportButton>;
107+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { FormFacet } from "@databiosphere/findable-ui/lib/components/Export/common/entities";
2+
import { FileManifestState } from "@databiosphere/findable-ui/lib/providers/fileManifestState";
3+
import { Filters } from "@databiosphere/findable-ui/lib/common/entities";
4+
5+
export interface Props {
6+
buttonLabel: string;
7+
description: string;
8+
fileManifestState: FileManifestState;
9+
fileSummaryFacetName: string;
10+
filters: Filters;
11+
formFacet: FormFacet;
12+
speciesFacetName: string;
13+
successTitle: string;
14+
title: string;
15+
}

app/components/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export {
1313
DownloadIconSmall,
1414
InventoryIconSmall,
1515
} from "@databiosphere/findable-ui/lib/components/common/CustomIcon/common/constants";
16+
export { ExportToPlatform } from "./Export/components/AnVILExplorer/platform/ExportToPlatform/exportToPlatform";
1617
export { DiscourseIcon } from "@databiosphere/findable-ui/lib/components/common/CustomIcon/components/DiscourseIcon/discourseIcon";
1718
export { GitHubIcon } from "@databiosphere/findable-ui/lib/components/common/CustomIcon/components/GitHubIcon/gitHubIcon";
1819
export { OpenInNewIcon } from "@databiosphere/findable-ui/lib/components/common/CustomIcon/components/OpenInNewIcon/openInNewIcon";

app/shared/entities.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/**
22
* Set of possible feature flags.
33
*/
4-
export enum FEATURES {}
4+
export enum FEATURES {
5+
NCPI_EXPORT = "ncpiexport",
6+
}

app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.ts

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,13 @@ import {
3939
ChipProps as MChipProps,
4040
FadeProps as MFadeProps,
4141
} from "@mui/material";
42-
import React, { ReactNode } from "react";
42+
import React, { ComponentProps, ReactNode } from "react";
4343
import {
4444
ANVIL_CMG_CATEGORY_KEY,
4545
ANVIL_CMG_CATEGORY_LABEL,
4646
DATASET_RESPONSE,
4747
} from "../../../../../site-config/anvil-cmg/category";
48-
import {
49-
ROUTE_EXPORT_TO_TERRA,
50-
ROUTE_MANIFEST_DOWNLOAD,
51-
} from "../../../../../site-config/anvil-cmg/dev/export/constants";
48+
import { ROUTES } from "../../../../../site-config/anvil-cmg/dev/export/routes";
5249
import {
5350
AggregatedBioSampleResponse,
5451
AggregatedDatasetResponse,
@@ -452,7 +449,7 @@ export const buildDatasetExportMethodManifestDownload = (
452449
buttonLabel: "Request File Manifest",
453450
description:
454451
"Request a file manifest suitable for downloading this dataset to your HPC cluster or local machine.",
455-
route: `${datasetPath}${ROUTE_MANIFEST_DOWNLOAD}`,
452+
route: `${datasetPath}${ROUTES.MANIFEST_DOWNLOAD}`,
456453
title: "Download a File Manifest with Metadata",
457454
};
458455
};
@@ -486,7 +483,7 @@ export const buildDatasetExportMethodTerra = (
486483
buttonLabel: "Analyze in Terra",
487484
description:
488485
"Terra is a biomedical research platform to analyze data using workflows, Jupyter Notebooks, RStudio, and Galaxy.",
489-
route: `${datasetPath}${ROUTE_EXPORT_TO_TERRA}`,
486+
route: `${datasetPath}${ROUTES.TERRA}`,
490487
title: "Export Dataset Data and Metadata to Terra Workspace",
491488
};
492489
};
@@ -744,7 +741,7 @@ export const buildExportMethodManifestDownload = (
744741
buttonLabel: "Request File Manifest",
745742
description:
746743
"Request a file manifest for the current query containing the full list of selected files and the metadata for each file.",
747-
route: ROUTE_MANIFEST_DOWNLOAD,
744+
route: ROUTES.MANIFEST_DOWNLOAD,
748745
title: "Download a File Manifest with Metadata for the Selected Data",
749746
};
750747
};
@@ -764,7 +761,7 @@ export const buildExportMethodTerra = (
764761
buttonLabel: "Analyze in Terra",
765762
description:
766763
"Terra is a biomedical research platform to analyze data using workflows, Jupyter Notebooks, RStudio, and Galaxy.",
767-
route: ROUTE_EXPORT_TO_TERRA,
764+
route: ROUTES.TERRA,
768765
title: "Export Study Data and Metadata to Terra Workspace",
769766
};
770767
};
@@ -793,6 +790,77 @@ export const buildExportSelectedDataSummary = (
793790
};
794791
};
795792

793+
/**
794+
* Build props for ExportToPlatform component.
795+
* @param props - Props to pass to the ExportToPlatform component.
796+
* @returns model to be used as props for the ExportToPlatform component.
797+
*/
798+
export const buildExportToPlatform = (
799+
props: Pick<
800+
ComponentProps<typeof C.ExportToPlatform>,
801+
"buttonLabel" | "description" | "successTitle" | "title"
802+
>
803+
): ((
804+
_: unknown,
805+
viewContext: ViewContext<unknown>
806+
) => ComponentProps<typeof C.ExportToPlatform>) => {
807+
return (_: unknown, viewContext: ViewContext<unknown>) => {
808+
const {
809+
exploreState: { filterState },
810+
fileManifestState,
811+
} = viewContext;
812+
return {
813+
...props,
814+
fileManifestState,
815+
fileSummaryFacetName: ANVIL_CMG_CATEGORY_KEY.FILE_FILE_FORMAT,
816+
filters: filterState,
817+
formFacet: getFormFacets(fileManifestState),
818+
speciesFacetName: ANVIL_CMG_CATEGORY_KEY.DONOR_ORGANISM_TYPE,
819+
};
820+
};
821+
};
822+
823+
/**
824+
* Build props for ExportToPlatform BackPageHero component.
825+
* @param title - Title of the export method.
826+
* @returns model to be used as props for the BackPageHero component.
827+
*/
828+
export const buildExportToPlatformHero = (
829+
title: string
830+
): ((
831+
_: unknown,
832+
viewContext: ViewContext<unknown>
833+
) => React.ComponentProps<typeof C.BackPageHero>) => {
834+
return (_, viewContext) => {
835+
const {
836+
exploreState: { tabValue },
837+
} = viewContext;
838+
return getExportMethodHero(tabValue, title);
839+
};
840+
};
841+
842+
/**
843+
* Build props for ExportMethod component for display of the export to [platform] metadata section.
844+
* @param props - Props to pass to the ExportMethod component.
845+
* @returns model to be used as props for the ExportMethod component.
846+
*/
847+
export const buildExportToPlatformMethod = (
848+
props: Pick<
849+
ComponentProps<typeof ExportMethod>,
850+
"buttonLabel" | "description" | "route" | "title"
851+
>
852+
): ((
853+
_: unknown,
854+
viewContext: ViewContext<unknown>
855+
) => ComponentProps<typeof ExportMethod>) => {
856+
return (_: unknown, viewContext: ViewContext<unknown>) => {
857+
return {
858+
...props,
859+
...getExportMethodAccessibility(viewContext),
860+
};
861+
};
862+
};
863+
796864
/**
797865
* Build props for ExportToTerra component.
798866
* @param _ - Unused.

e2e/anvil/anvil-dataset.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
DatasetAccess,
1111
} from "./common/constants";
1212
import { MUI_CLASSES } from "../features/common/constants";
13-
import { ROUTE_MANIFEST_DOWNLOAD } from "../../site-config/anvil-cmg/dev/export/constants";
13+
import { ROUTES } from "../../site-config/anvil-cmg/dev/export/routes";
1414
import { ANVIL_CMG_CATEGORY_KEY } from "../../site-config/anvil-cmg/category";
1515

1616
const { describe } = test;
@@ -88,7 +88,7 @@ describe("Dataset", () => {
8888

8989
// Navigate to the export file manifest page.
9090
const currentUrl = page.url();
91-
await page.goto(`${currentUrl}${ROUTE_MANIFEST_DOWNLOAD}`);
91+
await page.goto(`${currentUrl}${ROUTES.MANIFEST_DOWNLOAD}`);
9292

9393
// Confirm the login alert is displayed.
9494
await expect(

pages/export/biodata-catalyst.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { JSX } from "react";
2+
import { ExportMethodView } from "@databiosphere/findable-ui/lib/views/ExportMethodView/exportMethodView";
3+
import { GetStaticProps } from "next";
4+
import { useFeatureFlag } from "@databiosphere/findable-ui/lib/hooks/useFeatureFlag/useFeatureFlag";
5+
import { FEATURES } from "../../app/shared/entities";
6+
import Error from "next/error";
7+
8+
export const getStaticProps: GetStaticProps = async () => {
9+
return {
10+
props: {
11+
pageTitle: "Export to NHLBI BioData Catalyst",
12+
},
13+
};
14+
};
15+
16+
/**
17+
* Export method page for BioData Catalyst.
18+
* @returns export method view component.
19+
*/
20+
const ExportMethodPage = (): JSX.Element => {
21+
const isEnabled = useFeatureFlag(FEATURES.NCPI_EXPORT);
22+
23+
if (!isEnabled) return <Error statusCode={404} />;
24+
25+
return <ExportMethodView />;
26+
};
27+
28+
export default ExportMethodPage;

site-config/anvil-cmg/dev/detail/dataset/export/export.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ import { sideColumn as exportSideColumn } from "../../../export/exportSideColumn
66
import * as V from "../../../../../../app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders";
77
import * as C from "../../../../../../app/components";
88
import { DatasetsResponse } from "app/apis/azul/anvil-cmg/common/responses";
9-
import {
10-
ROUTE_EXPORT_TO_TERRA,
11-
ROUTE_MANIFEST_DOWNLOAD,
12-
} from "../../../export/constants";
9+
import { ROUTES } from "../../../export/routes";
1310
import * as MDX from "../../../../../../app/components/common/MDXContent/anvil-cmg";
1411

1512
/**
@@ -66,7 +63,7 @@ export const exportConfig: ExportConfig = {
6663
viewBuilder: V.renderDatasetExport,
6764
} as ComponentConfig<typeof C.ConditionalComponent, DatasetsResponse>,
6865
],
69-
route: ROUTE_EXPORT_TO_TERRA,
66+
route: ROUTES.TERRA,
7067
top: [
7168
{
7269
children: [DATASET_ACCESSIBILITY_BADGE],
@@ -119,7 +116,7 @@ export const exportConfig: ExportConfig = {
119116
viewBuilder: V.renderDatasetExport,
120117
} as ComponentConfig<typeof C.ConditionalComponent, DatasetsResponse>,
121118
],
122-
route: ROUTE_MANIFEST_DOWNLOAD,
119+
route: ROUTES.MANIFEST_DOWNLOAD,
123120
top: [
124121
{
125122
children: [DATASET_ACCESSIBILITY_BADGE],

0 commit comments

Comments
 (0)