From b86fa10e77583fd6a714a749794ece9548fb6885 Mon Sep 17 00:00:00 2001 From: Fran McDade <18710366+frano-m@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:56:12 +1000 Subject: [PATCH] feat: prevent users from initiating export of unfeasibly large anvil datasets (#4953) Co-Authored-By: Claude Opus 5.5 (1M context) --- .../viewModelBuilders/dataset-export.test.ts | 84 +++++++ __tests__/viewModelBuilders/export.test.ts | 160 ++++++++++++++ .../azul/anvil-cmg/common/constants.ts | 22 ++ .../anvil-cmg/common/viewModelBuilders.tsx | 206 +++++++++++++++++- .../dev/detail/dataset/export/export.ts | 35 ++- site-config/anvil-cmg/dev/export/export.ts | 30 ++- 6 files changed, 529 insertions(+), 8 deletions(-) create mode 100644 app/viewModelBuilders/azul/anvil-cmg/common/constants.ts diff --git a/__tests__/viewModelBuilders/dataset-export.test.ts b/__tests__/viewModelBuilders/dataset-export.test.ts index b2fc36117..072fdee47 100644 --- a/__tests__/viewModelBuilders/dataset-export.test.ts +++ b/__tests__/viewModelBuilders/dataset-export.test.ts @@ -4,9 +4,17 @@ import { FileFacet } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/ import { FileManifestState } from "@databiosphere/findable-ui/lib/providers/fileManifestState"; import { DatasetsResponse } from "../../app/apis/azul/anvil-cmg/common/responses"; import { + TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE, + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES, +} from "../../app/viewModelBuilders/azul/anvil-cmg/common/constants"; +import { + buildDatasetExportMethodTerra, buildDatasetExportToPlatform, buildDatasetExportToPlatformHero, buildDatasetExportToPlatformMethod, + isDatasetTerraExportUnavailable, + renderDatasetTerraExport, + renderDatasetTerraExportUnavailable, } from "../../app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders"; import { ANVIL_CMG_CATEGORY_KEY } from "../../site-config/anvil-cmg/category"; import { @@ -380,3 +388,79 @@ describe("buildDatasetExportToPlatformMethod", () => { }); }); }); + +/** + * Creates a mock DatasetsResponse with the given dataset title. + * @param title - Dataset title. + * @returns Mock DatasetsResponse. + */ +const createMockDatasetsResponseWithTitle = (title: string): DatasetsResponse => + createMockDatasetsResponse({ + datasets: [ + { + accessible: true, + dataset_id: "test-dataset-id", + title, + }, + ], + } as Partial); + +describe("isDatasetTerraExportUnavailable", () => { + it.each(TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES)( + "returns true for %s", + (title) => { + const response = createMockDatasetsResponseWithTitle(title); + + expect(isDatasetTerraExportUnavailable(response)).toBe(true); + } + ); + + it("returns false for any other dataset", () => { + const response = createMockDatasetsResponse(); + + expect(isDatasetTerraExportUnavailable(response)).toBe(false); + }); +}); + +describe("buildDatasetExportMethodTerra", () => { + it("returns inaccessible with footnote when Terra export is unavailable", () => { + const response = createMockDatasetsResponseWithTitle( + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES[0] + ); + + const result = buildDatasetExportMethodTerra(response); + + expect(result.isAccessible).toBe(false); + expect(result.footnote).toBe(TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE); + }); + + it("returns accessible without footnote when Terra export is available", () => { + const response = createMockDatasetsResponse(); + + const result = buildDatasetExportMethodTerra(response); + + expect(result.isAccessible).toBe(true); + expect(result.footnote).toBeNull(); + expect(result.route).toBe( + "/datasets/test-dataset-id/export/export-to-terra" + ); + }); +}); + +describe("renderDatasetTerraExport and renderDatasetTerraExportUnavailable", () => { + it("renders the warning, not the Terra export, when Terra export is unavailable", () => { + const response = createMockDatasetsResponseWithTitle( + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES[0] + ); + + expect(renderDatasetTerraExport(response).isIn).toBe(false); + expect(renderDatasetTerraExportUnavailable(response).isIn).toBe(true); + }); + + it("renders the Terra export, not the warning, when Terra export is available", () => { + const response = createMockDatasetsResponse(); + + expect(renderDatasetTerraExport(response).isIn).toBe(true); + expect(renderDatasetTerraExportUnavailable(response).isIn).toBe(false); + }); +}); diff --git a/__tests__/viewModelBuilders/export.test.ts b/__tests__/viewModelBuilders/export.test.ts index 98cffa0ab..2c9ee67e5 100644 --- a/__tests__/viewModelBuilders/export.test.ts +++ b/__tests__/viewModelBuilders/export.test.ts @@ -2,10 +2,16 @@ import { Breadcrumb } from "@databiosphere/findable-ui/lib/components/common/Bre import { ViewContext } from "@databiosphere/findable-ui/lib/config/entities"; import { FileFacet } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/common/entities"; import { FileManifestState } from "@databiosphere/findable-ui/lib/providers/fileManifestState"; +import { TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES } from "../../app/viewModelBuilders/azul/anvil-cmg/common/constants"; import { + buildAlertTerraExportUnavailable, + buildExportMethodTerra, buildExportToPlatform, buildExportToPlatformHero, buildExportToPlatformMethod, + getSelectedTerraExportUnavailableDatasetTitles, + renderCohortTerraExport, + renderCohortTerraExportUnavailable, } from "../../app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders"; import { ANVIL_CMG_CATEGORY_KEY } from "../../site-config/anvil-cmg/category"; import { @@ -339,3 +345,157 @@ describe("buildExportToPlatformMethod", () => { }); }); }); + +/** + * Creates a mock ViewContext with the given dataset title filter selected. + * @param datasetTitles - Selected dataset titles. + * @returns Mock ViewContext. + */ +const createMockViewContextWithDatasetTitles = ( + datasetTitles: string[] +): ViewContext => { + const viewContext = createMockViewContext(); + viewContext.exploreState.filterState = [ + { categoryKey: ANVIL_CMG_CATEGORY_KEY.DATASET_TITLE, value: datasetTitles }, + ]; + return viewContext; +}; + +describe("getSelectedTerraExportUnavailableDatasetTitles", () => { + it("returns selected datasets that cannot be exported to Terra", () => { + const [unavailableTitle] = TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES; + + const result = getSelectedTerraExportUnavailableDatasetTitles([ + { + categoryKey: ANVIL_CMG_CATEGORY_KEY.DATASET_TITLE, + value: [unavailableTitle, "ANVIL_Other_Dataset"], + }, + ]); + + expect(result).toEqual([unavailableTitle]); + }); + + it("returns an empty array when no dataset title filter is selected", () => { + const result = getSelectedTerraExportUnavailableDatasetTitles([ + { categoryKey: "test.filter", value: ["value1"] }, + ]); + + expect(result).toEqual([]); + }); + + it("returns an empty array when only other datasets are selected", () => { + const result = getSelectedTerraExportUnavailableDatasetTitles([ + { + categoryKey: ANVIL_CMG_CATEGORY_KEY.DATASET_TITLE, + value: ["ANVIL_Other_Dataset"], + }, + ]); + + expect(result).toEqual([]); + }); +}); + +describe("buildExportMethodTerra", () => { + it("ignores the selected datasets before the files facets have loaded", () => { + const viewContext = createMockViewContextWithDatasetTitles([ + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES[0], + ]); + viewContext.fileManifestState = createMockFileManifestState({ + isFacetsSuccess: false, + }); + + const result = buildExportMethodTerra(undefined, viewContext); + + expect(result.isAccessible).toBe(false); + expect(result.footnote).toBeNull(); + }); + + it("returns inaccessible with footnote naming the selected unavailable datasets", () => { + const [unavailableTitle] = TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES; + const viewContext = createMockViewContextWithDatasetTitles([ + unavailableTitle, + ]); + + const result = buildExportMethodTerra(undefined, viewContext); + + expect(result.isAccessible).toBe(false); + expect(result.footnote).toContain(unavailableTitle); + }); + + it("returns file manifest accessibility when no unavailable dataset is selected", () => { + const fileManifestState = createMockFileManifestState({ + filesFacets: [createMockFileFacet()], + isFacetsSuccess: true, + summary: { fileCount: 10 }, + }); + const viewContext = createMockViewContext({ fileManifestState }); + + const result = buildExportMethodTerra(undefined, viewContext); + + expect(result.isAccessible).toBe(true); + expect(result.footnote).toBeNull(); + }); +}); + +describe("renderCohortTerraExport and renderCohortTerraExportUnavailable", () => { + it("renders neither the warning nor the Terra export before the file manifest is enabled", () => { + const viewContext = createMockViewContextWithDatasetTitles([ + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES[0], + ]); + viewContext.fileManifestState = createMockFileManifestState({ + isEnabled: false, + }); + + expect(renderCohortTerraExport(undefined, viewContext).isIn).toBe(false); + expect( + renderCohortTerraExportUnavailable(undefined, viewContext).isIn + ).toBe(false); + }); + + it("renders the warning, not the Terra export, when an unavailable dataset is selected", () => { + const viewContext = createMockViewContextWithDatasetTitles([ + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES[0], + ]); + + expect(renderCohortTerraExport(undefined, viewContext).isIn).toBe(false); + expect( + renderCohortTerraExportUnavailable(undefined, viewContext).isIn + ).toBe(true); + }); + + it("renders the Terra export, not the warning, when no unavailable dataset is selected", () => { + const viewContext = createMockViewContext(); + + expect(renderCohortTerraExport(undefined, viewContext).isIn).toBe(true); + expect( + renderCohortTerraExportUnavailable(undefined, viewContext).isIn + ).toBe(false); + }); +}); + +describe("buildAlertTerraExportUnavailable", () => { + it("uses singular wording when one unavailable dataset is selected", () => { + const [title] = TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES; + const viewContext = createMockViewContextWithDatasetTitles([title]); + + const result = buildAlertTerraExportUnavailable(undefined, viewContext); + + expect(result.content).toBe( + `Export to Terra is unavailable for ${title} because its metadata is too large for Terra to import. Remove this dataset from the selection to export to Terra.` + ); + }); + + it("uses plural wording when several unavailable datasets are selected", () => { + const [firstTitle, secondTitle] = TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES; + const viewContext = createMockViewContextWithDatasetTitles([ + firstTitle, + secondTitle, + ]); + + const result = buildAlertTerraExportUnavailable(undefined, viewContext); + + expect(result.content).toBe( + `Export to Terra is unavailable for ${firstTitle}, ${secondTitle} because their metadata is too large for Terra to import. Remove these datasets from the selection to export to Terra.` + ); + }); +}); diff --git a/app/viewModelBuilders/azul/anvil-cmg/common/constants.ts b/app/viewModelBuilders/azul/anvil-cmg/common/constants.ts new file mode 100644 index 000000000..7c337e881 --- /dev/null +++ b/app/viewModelBuilders/azul/anvil-cmg/common/constants.ts @@ -0,0 +1,22 @@ +/** + * Titles of datasets that cannot be exported to Terra. Their verbatim PFB manifests are too large to generate, + * and Terra is unable to import them. + * See https://github.com/DataBiosphere/azul/issues/8134. + */ +export const TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES = [ + "ANVIL_eMERGE_GWAS_GRU", + "ANVIL_eMERGE_GWAS_HMB_GSO", + "ANVIL_eMERGE_GWAS_HMB_MDS", + "ANVIL_eMERGE_GWAS_HMB_PUB_GSO", +]; + +/** + * Reason Terra export is unavailable, shared by the dataset and cohort explanations. + */ +export const TERRA_EXPORT_UNAVAILABLE_REASON = + "metadata is too large for Terra to import"; + +/** + * Explanation displayed when Terra export is unavailable for a dataset. + */ +export const TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE = `Export to Terra is unavailable for this dataset because its ${TERRA_EXPORT_UNAVAILABLE_REASON}.`; diff --git a/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.tsx b/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.tsx index 3922818fc..0fcd83d68 100644 --- a/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.tsx +++ b/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.tsx @@ -113,6 +113,11 @@ import { ExportIcon } from "../../../../components/Export/components/AnVILExplor import { METADATA_KEY } from "../../../../components/Index/common/entities"; import { getPluralizedMetadataLabel } from "../../../../components/Index/common/indexTransformer"; import { isProductionEnvironment } from "../../../../config/utils"; +import { + TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE, + TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES, + TERRA_EXPORT_UNAVAILABLE_REASON, +} from "./constants"; import { SUMMARY_DISPLAY_TEXT } from "./summaryMapper/constants"; import { mapExportSummary } from "./summaryMapper/summaryMapper"; @@ -187,6 +192,20 @@ export const buildAlertDatasetManifestDownloadWarning = ( }; }; +/** + * Build props for dataset Terra export unavailable warning Alert component. + * @returns model to be used as props for the Alert component. + */ +export const buildAlertDatasetTerraExportUnavailable = (): React.ComponentProps< + typeof MDX.Alert +> => { + return { + ...ALERT_PROPS.STANDARD_WARNING, + component: C.FluidPaper, + content: TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE, + }; +}; + /** * Build props for list view access warning Alert component. * @param _ - Unused. @@ -223,6 +242,27 @@ export const buildAlertExportWarning = ( }; }; +/** + * Build props for cohort Terra export unavailable warning Alert component. + * @param _ - Unused. + * @param viewContext - View context. + * @returns model to be used as props for the Alert component. + */ +export const buildAlertTerraExportUnavailable = ( + _: unknown, + viewContext: ViewContext +): React.ComponentProps => { + return { + ...ALERT_PROPS.STANDARD_WARNING, + component: C.FluidPaper, + content: getTerraExportUnavailableMessage( + getSelectedTerraExportUnavailableDatasetTitles( + viewContext.exploreState.filterState + ) + ), + }; +}; + /** * Build props for the biosample IdentityCell component from the given biosamples response. * The biosample ID is the title, in plain text as biosamples have no detail page. The biosample type, anatomical site @@ -450,12 +490,14 @@ export const buildDatasetExportMethodTerra = ( datasetsResponse: DatasetsResponse ): React.ComponentProps => { const datasetPath = buildDatasetPath(datasetsResponse); + const isUnavailable = isDatasetTerraExportUnavailable(datasetsResponse); return { description: "Terra is a biomedical research platform to analyze data using workflows, Jupyter Notebooks, RStudio, and Galaxy.", + footnote: isUnavailable ? TERRA_EXPORT_UNAVAILABLE_DATASET_MESSAGE : null, icon: , + isAccessible: !isUnavailable, route: `${datasetPath}${ROUTES.TERRA}`, - title: "Export to Terra", }; }; @@ -759,6 +801,22 @@ export const buildExportCurrentQuery = ( }; }; +/** + * Build props for the ExportEntity component, for triggering calls to populate the selected data for the current + * cohort selection. + * @param _ - Unused. + * @param viewContext - View context. + * @returns model to be used as props for the ExportEntity component. + */ +export const buildExportEntityProps = ( + _: unknown, + viewContext: ViewContext +): React.ComponentProps => { + return { + filters: viewContext.exploreState.filterState, + }; +}; + /** * Build props for export BackPageHero component. * @param _ - Unused. @@ -844,7 +902,7 @@ export const buildExportMethodTerra = ( viewContext: ViewContext ): React.ComponentProps => { return { - ...getExportMethodAccessibility(viewContext), + ...getExportMethodTerraAccessibility(viewContext), description: "Terra is a biomedical research platform to analyze data using workflows, Jupyter Notebooks, RStudio, and Galaxy.", icon: , @@ -1541,6 +1599,30 @@ function getExportMethodHero( }; } +/** + * Returns the Terra export method accessibility. Terra export is inaccessible when the selected datasets include + * any dataset that cannot be exported to Terra. Selected datasets are only considered once the files facets have + * loaded; the selected filters are not known when the page is statically rendered, and considering them earlier + * would cause a hydration mismatch. + * @param viewContext - View context. + * @returns Terra export method accessibility. + */ +function getExportMethodTerraAccessibility( + viewContext: ViewContext +): Partial { + if (!viewContext.fileManifestState.isFacetsSuccess) + return getExportMethodAccessibility(viewContext); + const datasetTitles = getSelectedTerraExportUnavailableDatasetTitles( + viewContext.exploreState.filterState + ); + if (datasetTitles.length === 0) + return getExportMethodAccessibility(viewContext); + return { + footnote: getTerraExportUnavailableMessage(datasetTitles), + isAccessible: false, + }; +} + /** * Returns the export selected data summary for the given file manifest. * @param filesFacets - Files facets. @@ -1724,6 +1806,33 @@ function getIdentityDatasetsSubtitle( return { label: title, url: "" }; } +/** + * Returns the titles of datasets selected in the given filters that cannot be exported to Terra. + * @param filters - Selected filters. + * @returns titles of selected datasets that cannot be exported to Terra. + */ +export function getSelectedTerraExportUnavailableDatasetTitles( + filters: Filters +): string[] { + const datasetTitleFilter = filters.find( + ({ categoryKey }) => categoryKey === ANVIL_CMG_CATEGORY_KEY.DATASET_TITLE + ); + if (!datasetTitleFilter) return []; + return TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES.filter((title) => + datasetTitleFilter.value.includes(title) + ); +} + +/** + * Returns the explanation displayed when Terra export is unavailable for the selected datasets. + * @param datasetTitles - Titles of selected datasets that cannot be exported to Terra. + * @returns explanation of why Terra export is unavailable. + */ +function getTerraExportUnavailableMessage(datasetTitles: string[]): string { + const isSingular = datasetTitles.length === 1; + return `Export to Terra is unavailable for ${datasetTitles.join(", ")} because ${isSingular ? "its" : "their"} ${TERRA_EXPORT_UNAVAILABLE_REASON}. Remove ${isSingular ? "this dataset" : "these datasets"} from the selection to export to Terra.`; +} + /** * Boolean to filter out any selected filters that have dataset ID as the category key. * @param filter - Selected filter. @@ -1744,6 +1853,24 @@ function isAccessibleTransitionIn(datasetsResponse: DatasetsResponse): boolean { return isAccessible || isReady; } +/** + * Returns true if the selected datasets include any dataset that cannot be exported to Terra. + * The cohort Terra export components are rendered only once the file manifest is enabled (after hydration); the + * selected filters are not known when the page is statically rendered, and the Terra export component clears the + * file manifest when it unmounts. + * @param viewContext - View context. + * @returns true if the selected datasets include any dataset that cannot be exported to Terra. + */ +function isCohortTerraExportUnavailable( + viewContext: ViewContext +): boolean { + return ( + getSelectedTerraExportUnavailableDatasetTitles( + viewContext.exploreState.filterState + ).length > 0 + ); +} + /** * Returns true if dataset is accessible. * @param datasetsResponse - Response model return from datasets API. @@ -1768,6 +1895,19 @@ export function isDatasetNRESConsentGroup( ); } +/** + * Returns true if the dataset cannot be exported to Terra. + * @param datasetsResponse - Response model return from datasets API. + * @returns true if the dataset cannot be exported to Terra. + */ +export function isDatasetTerraExportUnavailable( + datasetsResponse: DatasetsResponse +): boolean { + return TERRA_EXPORT_UNAVAILABLE_DATASET_TITLES.includes( + getDatasetTitle(datasetsResponse) + ); +} + /** * Returns true if the "accessible" file facet has a term value of "true". * @param fileManifestState - File manifest state. @@ -1909,6 +2049,42 @@ export const renderCohortCurlDownload = ( }; }; +/** + * Renders cohort Terra export component, once the file manifest is enabled, when the selected datasets do not + * include any dataset that cannot be exported to Terra. + * @param _ - Unused. + * @param viewContext - View context. + * @returns model to be used as props for the ConditionalComponent component. + */ +export const renderCohortTerraExport = ( + _: unknown, + viewContext: ViewContext +): ComponentProps => { + return { + isIn: + viewContext.fileManifestState.isEnabled && + !isCohortTerraExportUnavailable(viewContext), + }; +}; + +/** + * Renders cohort Terra export unavailable warning component, once the file manifest is enabled, when the selected + * datasets include any dataset that cannot be exported to Terra. + * @param _ - Unused. + * @param viewContext - View context. + * @returns model to be used as props for the ConditionalComponent component. + */ +export const renderCohortTerraExportUnavailable = ( + _: unknown, + viewContext: ViewContext +): ComponentProps => { + return { + isIn: + viewContext.fileManifestState.isEnabled && + isCohortTerraExportUnavailable(viewContext), + }; +}; + /** * Renders dataset curl download components when the given dataset has NRES consent group, * or when the environment is non-production. @@ -1952,6 +2128,32 @@ export const renderDatasetExportWarning = ( }; }; +/** + * Renders dataset Terra export component when the given dataset can be exported to Terra. + * @param datasetsResponse - Response model return from datasets API. + * @returns model to be used as props for the ConditionalComponent component. + */ +export const renderDatasetTerraExport = ( + datasetsResponse: DatasetsResponse +): React.ComponentProps => { + return { + isIn: !isDatasetTerraExportUnavailable(datasetsResponse), + }; +}; + +/** + * Renders dataset Terra export unavailable warning component when the given dataset cannot be exported to Terra. + * @param datasetsResponse - Response model return from datasets API. + * @returns model to be used as props for the ConditionalComponent component. + */ +export const renderDatasetTerraExportUnavailable = ( + datasetsResponse: DatasetsResponse +): React.ComponentProps => { + return { + isIn: isDatasetTerraExportUnavailable(datasetsResponse), + }; +}; + /** * Returns value from a string array matching the given index. * @param arr - String array. diff --git a/site-config/anvil-cmg/dev/detail/dataset/export/export.ts b/site-config/anvil-cmg/dev/detail/dataset/export/export.ts index f4db4f1f1..a003a17cd 100644 --- a/site-config/anvil-cmg/dev/detail/dataset/export/export.ts +++ b/site-config/anvil-cmg/dev/detail/dataset/export/export.ts @@ -106,10 +106,39 @@ export const exportConfig: ExportConfig = { children: [ { children: [ + /* Dataset cannot be exported to Terra; render warning */ { - component: C.ExportToTerra, - viewBuilder: V.buildDatasetTerraExport, - } as ComponentConfig, + children: [ + // Empty component for triggering calls to populate the selected data in the side channel. + { + component: C.AnVILExportEntity, + viewBuilder: V.buildDatasetExportPropsWithFilter, + } as ComponentConfig, + { + component: MDX.Alert, + viewBuilder: V.buildAlertDatasetTerraExportUnavailable, + } as ComponentConfig, + ], + component: C.ConditionalComponent, + viewBuilder: V.renderDatasetTerraExportUnavailable, + } as ComponentConfig< + typeof C.ConditionalComponent, + DatasetsResponse + >, + /* Dataset can be exported to Terra; render Terra export */ + { + children: [ + { + component: C.ExportToTerra, + viewBuilder: V.buildDatasetTerraExport, + } as ComponentConfig, + ], + component: C.ConditionalComponent, + viewBuilder: V.renderDatasetTerraExport, + } as ComponentConfig< + typeof C.ConditionalComponent, + DatasetsResponse + >, ], component: C.BackPageContentMainColumn, } as ComponentConfig, diff --git a/site-config/anvil-cmg/dev/export/export.ts b/site-config/anvil-cmg/dev/export/export.ts index 818fc6e49..84ba6e86b 100644 --- a/site-config/anvil-cmg/dev/export/export.ts +++ b/site-config/anvil-cmg/dev/export/export.ts @@ -3,6 +3,7 @@ import { ExportConfig, } from "@databiosphere/findable-ui/lib/config/entities"; import * as C from "../../../../app/components"; +import * as MDX from "../../../../app/components/common/MDXContent/anvil-cmg"; import { DownloadSection } from "../../../../app/components/Export/components/AnVILExplorer/components/ExportCohort/components/DownloadSection/downloadSection"; import { ExportSection } from "../../../../app/components/Export/components/AnVILExplorer/components/ExportCohort/components/ExportSection/exportSection"; import * as V from "../../../../app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders"; @@ -45,10 +46,33 @@ export const exportConfig: ExportConfig = { /* mainColumn */ { children: [ + // Empty component for triggering calls to populate the selected data in the side channel. { - component: C.ExportToTerra, - viewBuilder: V.buildExportToTerra, - } as ComponentConfig, + component: C.AnVILExportEntity, + viewBuilder: V.buildExportEntityProps, + } as ComponentConfig, + /* Selected datasets include datasets that cannot be exported to Terra; render warning */ + { + children: [ + { + component: MDX.Alert, + viewBuilder: V.buildAlertTerraExportUnavailable, + } as ComponentConfig, + ], + component: C.ConditionalComponent, + viewBuilder: V.renderCohortTerraExportUnavailable, + } as ComponentConfig, + /* Selected datasets can be exported to Terra; render Terra export */ + { + children: [ + { + component: C.ExportToTerra, + viewBuilder: V.buildExportToTerra, + } as ComponentConfig, + ], + component: C.ConditionalComponent, + viewBuilder: V.renderCohortTerraExport, + } as ComponentConfig, ], component: C.BackPageContentMainColumn, } as ComponentConfig,