diff --git a/app/components/Export/components/AnVILExplorer/components/ExportEntity/exportEntity.tsx b/app/components/Export/components/AnVILExplorer/components/ExportEntity/exportEntity.tsx new file mode 100644 index 000000000..53fede3a1 --- /dev/null +++ b/app/components/Export/components/AnVILExplorer/components/ExportEntity/exportEntity.tsx @@ -0,0 +1,18 @@ +import { Filters } from "@databiosphere/findable-ui/lib/common/entities"; +import { useFileManifest } from "@databiosphere/findable-ui/lib/hooks/useFileManifest/useFileManifest"; + +export interface ExportEntityProps { + filters: Filters; +} + +/** + * Empty wrapper component that triggers calls to populate the selected data in the side channel. Required only + * for choose export method functionality (as individual export methods trigger the required calls themsleves). + * @param {Object} props - The properties object. + * @param {ExportEntityProps} props.filters - The base filters for displaying the selected data related. + * @returns Fragment. + */ +export const ExportEntity = ({ filters }: ExportEntityProps): JSX.Element => { + useFileManifest(filters); + return <>; +}; diff --git a/app/components/index.tsx b/app/components/index.tsx index 03336e852..8e9d586dd 100644 --- a/app/components/index.tsx +++ b/app/components/index.tsx @@ -95,6 +95,7 @@ export { FileNameCell } from "./Detail/components/GeneratedMatricesTables/compon export { GeneratedMatricesTables } from "./Detail/components/GeneratedMatricesTables/generatedMatricesTables"; export { AtlasSection } from "./Detail/components/Section/components/AtlasSection/atlasSection"; export { ManifestDownloadEntity as AnVILManifestDownloadEntity } from "./Export/components/AnVILExplorer/components/ManifestDownload/components/ManifestDownloadEntity/manifestDownloadEntity"; +export { ExportEntity as AnVILExportEntity } from "./Export/components/AnVILExplorer/components/ExportEntity/exportEntity"; export { BioNetworkCell } from "./Index/components/BioNetworkCell/bioNetworkCell"; export { ConsentCodesCell } from "./Index/components/ConsentCodesCell/consentCodesCell"; export { CopyCell } from "./Index/components/CopyCell/copyCell"; diff --git a/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.ts b/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.ts index 1ecb8573f..6da95403a 100644 --- a/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.ts +++ b/app/viewModelBuilders/azul/anvil-cmg/common/viewModelBuilders.ts @@ -111,6 +111,7 @@ import { FEATURE_FLAGS } from "../../../common/contants"; import { Unused, Void } from "../../../common/entities"; import { SUMMARY_DISPLAY_TEXT } from "./summaryMapper/constants"; import { mapExportSummary } from "./summaryMapper/summaryMapper"; +import { ExportEntity } from "app/components/Export/components/AnVILExplorer/components/ExportEntity/exportEntity"; /** * Build props for activity type BasicCell component from the given activities response. @@ -468,6 +469,22 @@ export const buildDatasetExportMethodManifestDownload = ( }; }; +/** + * Build props for either the ExportEntity component for the display of the choose export methods or + * the AnVILManifestDownloadEntity component for the display of the manifest download method. + * @param datasetsResponse - Response model return from datasets API. + * @returns model to be used as props for the ExportEntity component. + */ +export const buildDatasetExportPropsWithFilter = ( + datasetsResponse: DatasetsResponse +): + | React.ComponentProps + | typeof C.AnVILManifestDownloadEntity => { + return { + filters: getExportEntityFilters(datasetsResponse), + }; +}; + /** * Build props for ExportMethod component for display of the export to terra metadata section. * @param datasetsResponse - Response model return from datasets API. @@ -525,6 +542,35 @@ export function buildDatasetPath(datasetsResponse: DatasetsResponse): string { return `${URL_DATASETS}/${datasetId}`; } +/** + * Build props for dataset ExportToTerra component. + * @param datasetsResponse - Response model return from datasets API. + * @param viewContext - View context. + * @returns model to be used as props for the ExportToTerra component. + */ +export const builDatasetTerraExport = ( + datasetsResponse: DatasetsResponse, + viewContext: ViewContext +): React.ComponentProps => { + const { fileManifestState } = viewContext; + // Get the initial filters. + const filters = getExportEntityFilters(datasetsResponse); + // Grab the form facet. + const formFacet = getFormFacets(fileManifestState); + return { + ExportForm: C.ExportToTerraForm, + ExportToTerraStart: MDX.ExportToTerraStart, + ExportToTerraSuccess: MDX.ExportToTerraSuccess, + fileManifestState, + fileManifestType: FILE_MANIFEST_TYPE.ENTITY_EXPORT_TO_TERRA, + fileSummaryFacetName: ANVIL_CMG_CATEGORY_KEY.FILE_FILE_FORMAT, + filters, + formFacet, + manifestDownloadFormat: MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB, + manifestDownloadFormats: [MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB], + }; +}; + /** * Build dataset title Link component from the given datasets response. * @param datasetsResponse - Response model return from datasets API. @@ -624,35 +670,6 @@ export const buildExportCurrentQuery = ( }; }; -/** - * Build props for ExportToTerra component from the given datasets response. - * @param datasetsResponse - Response model return from datasets API. - * @param viewContext - View context. - * @returns model to be used as props for the ExportToTerra component. - */ -export const buildExportEntityToTerra = ( - datasetsResponse: DatasetsResponse, - viewContext: ViewContext -): React.ComponentProps => { - const { fileManifestState } = viewContext; - // Get the initial filters. - const filters = getExportEntityFilters(datasetsResponse); - // Grab the form facet. - const formFacet = getFormFacets(fileManifestState); - return { - ExportForm: C.ExportToTerraForm, - ExportToTerraStart: MDX.ExportToTerraStart, - ExportToTerraSuccess: MDX.ExportToTerraSuccess, - fileManifestState, - fileManifestType: FILE_MANIFEST_TYPE.ENTITY_EXPORT_TO_TERRA, - fileSummaryFacetName: ANVIL_CMG_CATEGORY_KEY.FILE_FILE_FORMAT, - filters, - formFacet, - manifestDownloadFormat: MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB, - manifestDownloadFormats: [MANIFEST_DOWNLOAD_FORMAT.VERBATIM_PFB], - }; -}; - /** * Build props for export BackPageHero component. * @param _ - Void. @@ -913,19 +930,6 @@ export const buildManifestDownload = ( }; }; -/* - * Build props for ManifestDownloadEntity component. - * @param datasetsResponse - Response model return from datasets API. - * @returns model to be used as props for the ManifestDownloadEntity component. - */ -export const buildManifestDownloadEntity = ( - datasetsResponse: DatasetsResponse -): React.ComponentProps => { - return { - filters: getExportEntityFilters(datasetsResponse), - }; -}; - /** * Build props for organism type BasicCell component from the given donors response. * @param response - Response model return from index/donors API endpoint. diff --git a/e2e/anvil/anvil-dataset.spec.ts b/e2e/anvil/anvil-dataset.spec.ts index fd22eec57..8fcdb294b 100644 --- a/e2e/anvil/anvil-dataset.spec.ts +++ b/e2e/anvil/anvil-dataset.spec.ts @@ -1,4 +1,4 @@ -import { expect, Locator, Page, test } from "@playwright/test"; +import { expect, Locator, Page, Request, test } from "@playwright/test"; import { BUTTON_TEXT_ANALYZE_IN_TERRA, BUTTON_TEXT_EXPORT, @@ -16,6 +16,11 @@ import { MUI_TABLE_ROW_ROOT, } from "../features/common/constants"; import { ROUTE_MANIFEST_DOWNLOAD } from "../../site-config/anvil-cmg/dev/export/constants"; +import { ANVIL_CMG_CATEGORY_KEY } from "../../site-config/anvil-cmg/category"; +import { + APIEndpoints, + AZUL_PARAM, +} from "@databiosphere/findable-ui/lib/apis/azul/common/entities"; const { describe } = test; @@ -40,6 +45,21 @@ describe.parallel("Dataset", () => { await expect(exportButton).toBeVisible(); }); + test("displays login to export method", async ({ page }) => { + await goToDataset(page, CHIP_TEXT_ACCESS_REQUIRED); + + // Navigate to the choose export method page. + const currentUrl = page.url(); + await page.goto(`${currentUrl}/export`); + + // Confirm the login alert is displayed. + await expect( + page.locator( + `${MUI_ALERT_ROOT}:has-text("To export this dataset, please sign in and, if necessary, request access.")` + ) + ).toBeVisible(); + }); + test("displays export method", async ({ page }) => { await goToDataset(page, CHIP_TEXT_ACCESS_GRANTED); @@ -55,6 +75,36 @@ describe.parallel("Dataset", () => { ).toBeVisible(); }); + test("displays export method selected data", async ({ page }) => { + await goToDataset(page, CHIP_TEXT_ACCESS_GRANTED); + + // Wait for the summary request once the export button is clicked. + const [request] = await Promise.all([ + page.waitForRequest((request) => + request.url().includes(APIEndpoints.SUMMARY) + ), + clickLink(page, BUTTON_TEXT_EXPORT), + ]); + + // Confirm summary request has dataset ID request param. + verifySummaryRequest(request); + }); + + test("displays login to download file manifest", async ({ page }) => { + await goToDataset(page, CHIP_TEXT_ACCESS_REQUIRED); + + // Navigate to the export file manifest page. + const currentUrl = page.url(); + await page.goto(`${currentUrl}${ROUTE_MANIFEST_DOWNLOAD}`); + + // Confirm the login alert is displayed. + await expect( + page.locator( + `${MUI_ALERT_ROOT}:has-text("To download this dataset manifest, please sign in and, if necessary, request access.")` + ) + ).toBeVisible(); + }); + test("displays download file manifest", async ({ page }) => { await goToDataset(page, CHIP_TEXT_ACCESS_GRANTED); @@ -76,37 +126,25 @@ describe.parallel("Dataset", () => { await expect(buttons.nth(1)).toBeVisible(); }); - test("displays login to export method", async ({ page }) => { - await goToDataset(page, CHIP_TEXT_ACCESS_REQUIRED); - - // Navigate to the choose export method page. - const currentUrl = page.url(); - await page.goto(`${currentUrl}/export`); - - // Confirm the login alert is displayed. - await expect( - page.locator( - `${MUI_ALERT_ROOT}:has-text("To export this dataset, please sign in and, if necessary, request access.")` - ) - ).toBeVisible(); - }); + test("displays download file manifest selected data", async ({ page }) => { + await goToDataset(page, CHIP_TEXT_ACCESS_GRANTED); - test("displays login to download file manifest", async ({ page }) => { - await goToDataset(page, CHIP_TEXT_ACCESS_REQUIRED); + // Confirm export button is visible and click it. + await clickLink(page, BUTTON_TEXT_EXPORT); - // Navigate to the export file manifest page. - const currentUrl = page.url(); - await page.goto(`${currentUrl}${ROUTE_MANIFEST_DOWNLOAD}`); + // Wait for the summary request once the file manifest button is clicked. + const [request] = await Promise.all([ + page.waitForRequest((request) => + request.url().includes(APIEndpoints.SUMMARY) + ), + clickLink(page, BUTTON_TEXT_REQUEST_FILE_MANIFEST), + ]); - // Confirm the login alert is displayed. - await expect( - page.locator( - `${MUI_ALERT_ROOT}:has-text("To download this dataset manifest, please sign in and, if necessary, request access.")` - ) - ).toBeVisible(); + // Confirm summary request has dataset ID request param. + verifySummaryRequest(request); }); - test("displays download analyze in Terra", async ({ page }) => { + test("displays analyze in Terra", async ({ page }) => { await goToDataset(page, CHIP_TEXT_ACCESS_GRANTED); // Confirm export button is visible and click it. @@ -174,3 +212,16 @@ async function goToDataset(page: Page, access: DatasetAccess): Promise { // Wait for the dataset detail page to load (specifically the dataset title). await page.waitForSelector(`h1:has-text("${datasetTitle}")`); } + +/** + * Confirm dataset ID is in the /summary request URL. + * @param request - The request object. + */ +function verifySummaryRequest(request: Request): void { + // Grab the filters param from the request. + const url = new URL(request.url()); + const paramValue = url.searchParams.get(AZUL_PARAM.FILTERS) || ""; + + // Validate dataset ID is in the filters query parameter. + expect(paramValue).toContain(ANVIL_CMG_CATEGORY_KEY.DATASET_ID); +} diff --git a/package.json b/package.json index 577a1f21d..e98a1ae87 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "check-system-status:anvil-cmg": "esrun e2e/anvil/anvil-check-system-status.ts" }, "dependencies": { - "@databiosphere/findable-ui": "21.1.0", + "@databiosphere/findable-ui": "21.1.1", "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@mdx-js/loader": "^3.0.1", 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 9f8bf746c..01e22f31f 100644 --- a/site-config/anvil-cmg/dev/detail/dataset/export/export.ts +++ b/site-config/anvil-cmg/dev/detail/dataset/export/export.ts @@ -54,7 +54,7 @@ export const exportConfig: ExportConfig = { children: [ { component: C.ExportToTerra, - viewBuilder: V.buildExportToTerra, + viewBuilder: V.builDatasetTerraExport, } as ComponentConfig, ], component: C.BackPageContentMainColumn, @@ -104,7 +104,7 @@ export const exportConfig: ExportConfig = { children: [ { component: C.AnVILManifestDownloadEntity, - viewBuilder: V.buildManifestDownloadEntity, + viewBuilder: V.buildDatasetExportPropsWithFilter, } as ComponentConfig< typeof C.AnVILManifestDownloadEntity, DatasetsResponse @@ -143,7 +143,6 @@ export const exportConfig: ExportConfig = { children: [ { component: MDX.Alert, - // TODO(cc) update text viewBuilder: V.buildAlertDatasetExportWarning, } as ComponentConfig, ], @@ -160,6 +159,11 @@ export const exportConfig: ExportConfig = { children: [ { children: [ + // Empty component for triggering calls to populate the selected data in the side channel. + { + component: C.AnVILExportEntity, + viewBuilder: V.buildDatasetExportPropsWithFilter, + } as ComponentConfig, { component: C.ExportMethod, viewBuilder: V.buildDatasetExportMethodTerra,