From 2260bfc4b86e1a6f0ca871e35239875698016fa6 Mon Sep 17 00:00:00 2001 From: Gregory Rushton Date: Tue, 12 Nov 2024 10:52:39 -0500 Subject: [PATCH] DT-530: Add conditional rendering around apply for access (#2718) --- cypress/component/Dataset/dataset.json | 138 +++++++++++++++ .../Dataset/datasetStatistics.spec.js | 167 ++++++++++++++++++ src/libs/Models.ts | 6 + src/pages/DatasetStatistics.jsx | 121 ++++++++----- 4 files changed, 384 insertions(+), 48 deletions(-) create mode 100644 cypress/component/Dataset/dataset.json create mode 100644 cypress/component/Dataset/datasetStatistics.spec.js create mode 100644 src/libs/Models.ts diff --git a/cypress/component/Dataset/dataset.json b/cypress/component/Dataset/dataset.json new file mode 100644 index 000000000..cc2a8252f --- /dev/null +++ b/cypress/component/Dataset/dataset.json @@ -0,0 +1,138 @@ +{ + "datasetId": 1975, + "name": "ExteranlAccessTestJL1", + "datasetName": "ExteranlAccessTestJL1", + "createDate": "Nov 2, 2023", + "createUserId": 3396, + "updateDate": 1730999135936, + "updateUserId": 3351, + "alias": 682, + "datasetIdentifier": "DUOS-000682", + "dataUse": { + "generalUse": true, + "hmbResearch": false, + "diseaseRestrictions": [], + "populationOriginsAncestry": false, + "ethicsApprovalRequired": false, + "collaboratorRequired": true, + "geneticStudiesOnly": true, + "publicationResults": true, + "controls": false, + "population": false + }, + "deletable": false, + "properties": [ + { + "propertyId": 9311, + "datasetId": 1975, + "propertyName": "Data Location", + "propertyValue": "Not Determined", + "schemaProperty": "dataLocation", + "propertyType": "String" + }, + { + "propertyId": 9312, + "datasetId": 1975, + "propertyName": "# of participants", + "propertyValue": 1, + "schemaProperty": "numberOfParticipants", + "propertyType": "Number" + }, + { + "propertyId": 9313, + "datasetId": 1975, + "propertyName": "File Types", + "propertyValue": [ + {} + ], + "schemaProperty": "fileTypes", + "propertyType": "Json" + } + ], + "createUser": { + "userId": 3396, + "email": "jlawson@broadinstitute.org", + "displayName": "Jonathan Lawson (Admin \u0026 DAC Member)", + "createDate": 1526056488000, + "emailPreference": false, + "institutionId": 150, + "eraCommonsId": "a" + }, + "study": { + "studyId": 5854, + "name": "ExternalAccessTestJL1", + "description": "ExternalAccessTestJL1", + "publicVisibility": true, + "piName": "Dr. Make", + "dataTypes": [ + "Hybrid Capture" + ], + "datasetIds": [ + 1975, + 1976, + 1977 + ], + "properties": [ + { + "studyPropertyId": 5860, + "studyId": 5854, + "key": "collaboratingSites", + "type": "Json", + "value": [] + }, + { + "studyPropertyId": 5855, + "studyId": 5854, + "key": "species", + "type": "String", + "value": "ExternalAccessTestJL1" + }, + { + "studyPropertyId": 5857, + "studyId": 5854, + "key": "dataCustodianEmail", + "type": "Json", + "value": [ + "geraldg@spurs.bb" + ] + }, + { + "studyPropertyId": 5858, + "studyId": 5854, + "key": "nihAnvilUse", + "type": "String", + "value": "I am not NHGRI funded and do not plan to store data in AnVIL" + }, + { + "studyPropertyId": 5854, + "studyId": 5854, + "key": "phenotypeIndication", + "type": "String", + "value": "ExternalAccessTestJL1" + }, + { + "studyPropertyId": 5859, + "studyId": 5854, + "key": "nihICsSupportingStudy", + "type": "Json", + "value": [] + }, + { + "studyPropertyId": 5853, + "studyId": 5854, + "key": "studyType", + "type": "String", + "value": "Observational" + }, + { + "studyPropertyId": 5861, + "studyId": 5854, + "key": "alternativeDataSharingPlanReasons", + "type": "Json", + "value": [] + } + ], + "createDate": 1698897809861, + "createUserId": 3396 + } +} diff --git a/cypress/component/Dataset/datasetStatistics.spec.js b/cypress/component/Dataset/datasetStatistics.spec.js new file mode 100644 index 000000000..465943e64 --- /dev/null +++ b/cypress/component/Dataset/datasetStatistics.spec.js @@ -0,0 +1,167 @@ +/* eslint-disable no-undef,no-console */ + +import React from 'react'; +import {mount} from 'cypress/react'; +import DatasetStatistics from '../../../src/pages/DatasetStatistics'; +import dataset from './dataset.json'; +import {DataSet} from '../../../src/libs/ajax/DataSet'; +import {DatasetMetrics} from '../../../src/libs/ajax/DatasetMetrics'; + +const externalProp = { + 'propertyId': 9314, + 'datasetId': 1975, + 'propertyName': 'Access Management', + 'propertyValue': 'external', + 'schemaProperty': 'accessManagement', + 'propertyType': 'String' +}; + +const openProp = { + 'propertyId': 9314, + 'datasetId': 1975, + 'propertyName': 'Access Management', + 'propertyValue': 'open', + 'schemaProperty': 'accessManagement', + 'propertyType': 'String' +}; + +const controlledProp = { + 'propertyId': 9314, + 'datasetId': 1975, + 'propertyName': 'Access Management', + 'propertyValue': 'controlled', + 'schemaProperty': 'accessManagement', + 'propertyType': 'String' +}; + +const location = { + 'propertyId': 12657, + 'datasetId': 1975, + 'propertyName': 'URL', + 'propertyValue': 'https://duos.org', + 'schemaProperty': 'url', + 'propertyType': 'String' +}; + +describe('Dataset Statistics Tests', () => { + + it('Displays Controlled Access Dataset Apply Button', () => { + const controlled = Object.assign(dataset, {properties: [controlledProp]}); + cy.viewport(600, 800); + cy.stub(DataSet, 'getDatasetByDatasetIdentifier').returns(Promise.resolve(controlled)); + cy.stub(DataSet, 'getDataSetsByDatasetId').returns(Promise.resolve(controlled)); + cy.stub(DatasetMetrics, 'getDatasetStats').returns(Promise.resolve({})); + + const props = { + match: { + params: { + datasetIdentifier: controlled.datasetIdentifier + } + }, + history: { + push() { + } + } + }; + mount(); + cy.contains(controlled.datasetIdentifier).should('exist'); + cy.contains('Apply for Access').should('exist'); + }); + + it('Displays External Access Language With Location', () => { + const external = Object.assign(dataset, {properties: [externalProp, location]}); + cy.viewport(600, 800); + cy.stub(DataSet, 'getDatasetByDatasetIdentifier').returns(Promise.resolve(external)); + cy.stub(DataSet, 'getDataSetsByDatasetId').returns(Promise.resolve(external)); + cy.stub(DatasetMetrics, 'getDatasetStats').returns(Promise.resolve({})); + + const props = { + match: { + params: { + datasetIdentifier: external.datasetIdentifier + } + }, + history: { + push() { + } + } + }; + mount(); + cy.contains(external.datasetIdentifier).should('exist'); + cy.contains('This dataset is externally managed').should('exist'); + cy.contains('Requests cannot be made via DUOS, but must be made directly').should('exist'); + }); + + it('Displays External Access Language Without Location', () => { + const external = Object.assign(dataset, {properties: [externalProp]}); + cy.viewport(600, 800); + cy.stub(DataSet, 'getDatasetByDatasetIdentifier').returns(Promise.resolve(external)); + cy.stub(DataSet, 'getDataSetsByDatasetId').returns(Promise.resolve(external)); + cy.stub(DatasetMetrics, 'getDatasetStats').returns(Promise.resolve({})); + + const props = { + match: { + params: { + datasetIdentifier: external.datasetIdentifier + } + }, + history: { + push() { + } + } + }; + mount(); + cy.contains(external.datasetIdentifier).should('exist'); + cy.contains('This dataset is externally managed').should('exist'); + cy.contains('Requests cannot be made via DUOS, but must be made directly').should('not.exist'); + }); + + it('Displays Open Access Language With Location', () => { + const open = Object.assign(dataset, {properties: [openProp, location]}); + cy.viewport(600, 800); + cy.stub(DataSet, 'getDatasetByDatasetIdentifier').returns(Promise.resolve(open)); + cy.stub(DataSet, 'getDataSetsByDatasetId').returns(Promise.resolve(open)); + cy.stub(DatasetMetrics, 'getDatasetStats').returns(Promise.resolve({})); + + const props = { + match: { + params: { + datasetIdentifier: open.datasetIdentifier + } + }, + history: { + push() { + } + } + }; + mount(); + cy.contains(open.datasetIdentifier).should('exist'); + cy.contains('This dataset is open access, does not require an access request').should('exist'); + cy.contains('and can be accessed directly').should('exist'); + }); + + it('Displays Open Access Language Without Location', () => { + const open = Object.assign(dataset, {properties: [openProp]}); + cy.viewport(600, 800); + cy.stub(DataSet, 'getDatasetByDatasetIdentifier').returns(Promise.resolve(open)); + cy.stub(DataSet, 'getDataSetsByDatasetId').returns(Promise.resolve(open)); + cy.stub(DatasetMetrics, 'getDatasetStats').returns(Promise.resolve({})); + + const props = { + match: { + params: { + datasetIdentifier: open.datasetIdentifier + } + }, + history: { + push() { + } + } + }; + mount(); + cy.contains(open.datasetIdentifier).should('exist'); + cy.contains('This dataset is open access, does not require an access request').should('exist'); + cy.contains('and can be accessed directly').should('not.exist'); + }); + +}); diff --git a/src/libs/Models.ts b/src/libs/Models.ts new file mode 100644 index 000000000..e0532b422 --- /dev/null +++ b/src/libs/Models.ts @@ -0,0 +1,6 @@ + +export enum AccessManagement { + OPEN = 'open', + CONTROLLED = 'controlled', + EXTERNAL = 'external' +} diff --git a/src/pages/DatasetStatistics.jsx b/src/pages/DatasetStatistics.jsx index 7b256b3da..174431f70 100644 --- a/src/pages/DatasetStatistics.jsx +++ b/src/pages/DatasetStatistics.jsx @@ -1,19 +1,20 @@ import React from 'react'; -import { useCallback, useState, useEffect } from 'react'; -import { DatasetMetrics } from '../libs/ajax/DatasetMetrics'; -import { DataSet } from '../libs/ajax/DataSet'; -import { DAR } from '../libs/ajax/DAR'; -import { Notifications } from '../libs/utils'; -import { Styles, Theme } from '../libs/theme'; -import { find } from 'lodash/fp'; -import { ReadMore } from '../components/ReadMore'; -import { formatDate } from '../libs/utils'; -import { Button } from '@mui/material'; +import {useCallback, useState, useEffect} from 'react'; +import {DatasetMetrics} from '../libs/ajax/DatasetMetrics'; +import {DataSet} from '../libs/ajax/DataSet'; +import {DAR} from '../libs/ajax/DAR'; +import {Notifications} from '../libs/utils'; +import {Styles, Theme} from '../libs/theme'; +import {find} from 'lodash/fp'; +import {ReadMore} from '../components/ReadMore'; +import {formatDate} from '../libs/utils'; +import {Button} from '@mui/material'; +import {AccessManagement} from '../libs/Models.ts'; -const LINE =
; +const LINE =
; export default function DatasetStatistics(props) { - const { history, match: { params: { datasetIdentifier }} } = props; + const {history, match: {params: {datasetIdentifier}}} = props; const [datasetId, setDatasetId] = useState(); const [dataset, setDataset] = useState(); const [dars, setDars] = useState(); @@ -21,16 +22,16 @@ export default function DatasetStatistics(props) { const applyForAccess = async () => { try { - const draftResponse = await DAR.postDarDraft({ datasetId: [datasetId] }); + const draftResponse = await DAR.postDarDraft({datasetId: [datasetId]}); if (draftResponse.referenceId) { history.push(`/dar_application/${draftResponse.referenceId}`); } else if (draftResponse.message) { - Notifications.showError({ text: draftResponse.message + ' Please contact customer support for help.' }); + Notifications.showError({text: draftResponse.message + ' Please contact customer support for help.'}); } else { - Notifications.showError({ text: 'Error: Unable to create a Draft Data Access Request' }); + Notifications.showError({text: 'Error: Unable to create a Draft Data Access Request'}); } } catch (error) { - Notifications.showError({ text: 'Error: Unable to create a Draft Data Access Request' }); + Notifications.showError({text: 'Error: Unable to create a Draft Data Access Request'}); } }; @@ -38,12 +39,12 @@ export default function DatasetStatistics(props) { DataSet.getDatasetByDatasetIdentifier(datasetIdentifier).then((dataset) => { setData(dataset.datasetId); }).catch(() => { - Notifications.showError({ text: 'Error: Unable to retrieve dataset from server' }); + Notifications.showError({text: 'Error: Unable to retrieve dataset from server'}); }); }, [datasetIdentifier]); const extract = useCallback((propertyName) => { - const property = find({ propertyName })(dataset.properties); + const property = find({propertyName})(dataset.properties); return property?.propertyValue; }, [dataset]); @@ -57,57 +58,81 @@ export default function DatasetStatistics(props) { setDars(metrics.dars); setIsLoading(false); } catch (error) { - Notifications.showError({ text: 'Error: Unable to retrieve dataset statistics from server' }); + Notifications.showError({text: 'Error: Unable to retrieve dataset statistics from server'}); setIsLoading(false); } }; + const accessInstructions = () => { + const accessManagement = extract('Access Management').toLowerCase(); + const locationUrl = extract('URL'); + switch (accessManagement) { + case AccessManagement.CONTROLLED: + return ; + case AccessManagement.OPEN: + return This dataset is open access, does not require an access request + {locationUrl && + , and can be accessed directly through this link. + } + ; + case AccessManagement.EXTERNAL: + return This dataset is externally managed. Requests cannot be made via DUOS + {locationUrl && + , but must be made directly through the dataset's host repository. + } + ; + default: + return
; + } + }; + if (!isLoading) { return ( -
-
-
+
+
+
Dataset Statistics
-
Dataset ID:
-
{dataset?.alias}
+
Dataset ID:
+
{dataset?.datasetIdentifier}
-
Dataset Name:
+
Dataset Name:
{extract('Dataset Name') || dataset?.name}
-
- +
+ {accessInstructions()}
Dataset Information
-
+
-
Dataset Description:
+
Dataset Description:
{LINE} -
- {extract('Dataset Description') || dataset?.description || dataset?.study?.description || 'N/A' } +
+ {extract('Dataset Description') || dataset?.description || dataset?.study?.description || 'N/A'}
-
-
Number of Participants:
+
+
Number of Participants:
{extract('# of participants')}
- {(extract('Principal Investigator(PI)') || dataset?.study?.piName) &&
-
Principal Investigator:
+ {(extract('Principal Investigator(PI)') || dataset?.study?.piName) &&
+
Principal Investigator:
{extract('Principal Investigator(PI)') || dataset?.study?.piName}
} - {(extract('Data Depositor') || dataset?.createUser?.displayName) &&
-
Data Custodian:
+ {(extract('Data Depositor') || dataset?.createUser?.displayName) &&
+
Data Custodian:
{extract('Data Depositor') || dataset?.createUser?.displayName}
@@ -121,24 +146,24 @@ export default function DatasetStatistics(props) { props={props} readLessText='Show less' readMoreText='Show More' - readStyle={{ fontWeight: 500, margin: '20px', height: 0 }} + readStyle={{fontWeight: 500, margin: '20px', height: 0}} content={[ -
-
{dar.darCode}
-
{dar.projectTitle}
+
+
{dar.darCode}
+
{dar.projectTitle}
, LINE ]} moreContent={[ -
-
-
Last Updated:
+
+
+
Last Updated:
{formatDate(dar.updateDate)}
, -
+
NonTechnical Summary:
-
+
{dar.nonTechRus}
,