From 66897f5a4d18992e79f5cee6bb448aff61af942f Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Mon, 12 May 2025 23:27:29 -0400 Subject: [PATCH 1/8] feat: Implement the DUOS Data Library Card --- src/pages/Home.jsx | 105 +++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 069858b3b..04f21ce10 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -1,9 +1,11 @@ import React from 'react'; -import { ReadMore } from '../components/ReadMore'; import homeHeaderBackground from '../images/home_header_background.png'; import duosLogoImg from '../images/duos_logo.svg'; import duosDiagram from '../images/DUOS_Homepage_diagram.svg'; -import { Link } from 'react-router-dom'; +import broadLogo from '../images/broad_logo_allwhite.png'; +import anvilLogo from '../images/anvil-logo.svg'; +import hcaLogo from '../images/human-cell-atlas-logo.png'; +import { Tooltip } from '@mui/material'; const Home = (props) => { @@ -61,24 +63,40 @@ const Home = (props) => { padding: '10px 1rem', }; - const paragraph = { - color: '#1F3B50', - padding: '0 5rem 2rem 5rem', - fontFamily: 'Montserrat', - fontSize: '14px', - textAlign: 'justify', - textIndent: '10px' + const logoGrid = { + display: 'flex', + gap: '3rem', + justifyContent: 'center', + alignItems: 'center', + flexWrap: 'nowrap', + width: '100%', }; - const readMoreStyle = { - fontFamily: 'Montserrat', - fontSize: '14px', - fontWeight: 500, - textAlign: 'center', - display: 'block' + const baseCard = { + width: 'clamp(240px, 26vw, 320px)', + aspectRatio: '2 / 1', + borderRadius: '6px', + boxShadow: '0 1px 4px rgba(0,0,0,0.06)', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + position: 'relative', + }; + + const logoImg = { + width: '100%', + height: '100%', + objectFit: 'contain', + display: 'block', }; return ( + <> +
@@ -125,37 +143,42 @@ const Home = (props) => {
-
-
-
-

Overview of DUOS

- - Increasingly, a major challenge to data sharing is navigating the complex web of restrictions on secondary data use. Human subjects datasets often have complex and/or ambiguous restrictions on future use deduced from the original consent form, which must be respected when utilizing data. Previously, such data use restrictions were uniquely drafted across institutions, creating vast inconsistencies and requiring the investment of significant human effort to determine if researchers should be permitted to use the data. With support from DUOS team members, the Global Alliance for Genomics and Health (GA4GH) published a solution for this ambiguous and inconsistent data sharing language in the form of their - {' '} - Machine Readable Consent Guidance. - {' '} - For help determining your data's permitted uses, try our - {' '} - Data Sharing Language Tool, which follows GA4GH guidelines. -

- ]} - moreContent={[ -
-

As part of our efforts to enhance collaborative research, the Broad Institute developed the “Data Use Oversight System” (DUOS) to semi-automate and efficiently manage compliant sharing of human subjects data. DUOS' objective is two-fold, to enhance data access committee's confidence that data use restrictions are respected while efficiently enabling appropriate data access.

-

To better enable the use of existing human subjects datasets in future projects, DUOS mimics, in a semi-automated fashion, the data access request review processes common to DACs globally, like those in dbGaP. To this end, the system includes interfaces to capture and structure data use restrictions and data access requests as machine-readable data use terms based on the GA4GH's Data Use Ontology. With these machine-readable terms for dataset's use limitations and data access requests established, DUOS is able to trigger a matching algorithm to reason if data access should be granted given the research purpose and the data restrictions, serving as a decision support tool for DACs using DUOS.

-

To evaluate the feasibility of using machine readable data use terms to interpret data use restrictions and access requests, we are piloting a trial of DUOS overseen by Partners’ Healthcare IRB. During the pilot, DACs comprised of governmental and non-governmental data custodians will pilot the use of DUOS, its ability to structure use limitations and access requests, and the accuracy of the DUOS algorithm. This aids us in improving the DUOS algorithm and providing feedback on the GA4GH Data Use Ontology based on experts’ feedback.

+ +
+
+

Data Libraries in DUOS

+

Click the images below to view curated Data Libraries, and search and request access to data.

+ +
-
+
+ ); }; From bfcfeb13fccc4315a11197c14ac92b1952e77568 Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Mon, 12 May 2025 23:55:40 -0400 Subject: [PATCH 2/8] feat: Remove unused props --- src/pages/Home.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 04f21ce10..0b9fc237a 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -7,7 +7,7 @@ import anvilLogo from '../images/anvil-logo.svg'; import hcaLogo from '../images/human-cell-atlas-logo.png'; import { Tooltip } from '@mui/material'; -const Home = (props) => { +const Home = () => { const homeTitle = { color: '#FFFFFF', From 504a6458c8eccedebd5166b198f88254fed2dec0 Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Sat, 17 May 2025 10:34:31 -0400 Subject: [PATCH 3/8] feat: Update anchor tags to Link components --- src/pages/Home.jsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 0b9fc237a..ccb1920d4 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -6,6 +6,7 @@ import broadLogo from '../images/broad_logo_allwhite.png'; import anvilLogo from '../images/anvil-logo.svg'; import hcaLogo from '../images/human-cell-atlas-logo.png'; import { Tooltip } from '@mui/material'; +import { Link } from 'react-router-dom'; const Home = () => { @@ -151,27 +152,27 @@ const Home = () => {
- +
AnVIL
-
+
- +
Broad Institute
-
+
- +
Human Cell Atlas
-
+
From c9dc3d472134a50645bfd5664fd16b182c4f6fe1 Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Sat, 17 May 2025 10:56:01 -0400 Subject: [PATCH 4/8] refactor: Update the tooltip component --- src/pages/Home.jsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index ccb1920d4..770835703 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -5,7 +5,7 @@ import duosDiagram from '../images/DUOS_Homepage_diagram.svg'; import broadLogo from '../images/broad_logo_allwhite.png'; import anvilLogo from '../images/anvil-logo.svg'; import hcaLogo from '../images/human-cell-atlas-logo.png'; -import { Tooltip } from '@mui/material'; +import { OverflowTooltip } from '../components/Tooltips'; import { Link } from 'react-router-dom'; const Home = () => { @@ -151,29 +151,29 @@ const Home = () => {

Click the images below to view curated Data Libraries, and search and request access to data.

- +
AnVIL
-
+ - +
Broad Institute
-
+ - +
Human Cell Atlas
-
+
From 5898b2f85482968a23c44f8fde4fe505c38b16ca Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Sat, 17 May 2025 11:49:02 -0400 Subject: [PATCH 5/8] feat: Write a test for the Home Page --- cypress/component/Home/home.spec.jsx | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 cypress/component/Home/home.spec.jsx diff --git a/cypress/component/Home/home.spec.jsx b/cypress/component/Home/home.spec.jsx new file mode 100644 index 000000000..e85b0a700 --- /dev/null +++ b/cypress/component/Home/home.spec.jsx @@ -0,0 +1,53 @@ +/* eslint-disable no-undef */ +import React from 'react'; +import { mount } from 'cypress/react'; +import { MemoryRouter } from 'react-router-dom'; +import Home from '../../../src/pages/Home'; + +describe('Home Page - Tests', function() { + beforeEach(() => { + mount( + + + + ); + }); + + it('renders the page header correctly', function() { + cy.contains('Data Use Oversight System').should('be.visible'); + cy.contains('Expediting compliant data sharing').should('be.visible'); + }); + + it('renders the Data Libraries section with correct header', function() { + cy.contains('Data Libraries in DUOS').should('be.visible'); + cy.contains('Click the images below to view curated Data Libraries, and search and request access to data.') + .should('be.visible'); + }); + + /** + * The native HTML title attribute creates a browser tooltip on hover, but these tooltips are not separate DOM elements - they're just a browser feature triggered by the attribute. That's why you don't see separate tooltip elements in the DOM. The test checks the presence of elements with the appropriate title attributes. + */ + it('displays tooltips with correct text for data libraries', function() { + cy.get('[data-for="anvil"]').find('span[title="AnVIL"]').should('exist'); + cy.get('[data-for="broad"]').find('span[title="Broad Institute"]').should('exist'); + cy.get('[data-for="hca"]').find('span[title="Human Cell Atlas"]').should('exist'); + }); + + it('has correct navigation links for data libraries', function() { + cy.get('a[href="/datalibrary/anvil"]').should('exist'); + cy.get('a[href="/datalibrary/broad"]').should('exist'); + cy.get('a[href="/datalibrary/HCA"]').should('exist'); + }); + + it('displays logos horizontally on desktop', function() { + cy.viewport(1200, 800); + cy.get('.logo-grid').should('have.css', 'flex-direction', 'row'); + cy.get('.logo-card').should('have.length', 3); + }); + + it('displays logos vertically on mobile', function() { + cy.viewport(600, 800); + cy.get('.logo-grid').should('have.css', 'flex-direction', 'column'); + cy.get('.logo-card').should('have.length', 3); + }); +}); \ No newline at end of file From 34a4f1fa41092883198f03303e9dcc40b1a55236 Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Tue, 20 May 2025 11:48:36 -0400 Subject: [PATCH 6/8] feat: Add visual indication for data library access requiring login --- src/pages/Home.jsx | 58 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 770835703..ad19f0027 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -8,7 +8,8 @@ import hcaLogo from '../images/human-cell-atlas-logo.png'; import { OverflowTooltip } from '../components/Tooltips'; import { Link } from 'react-router-dom'; -const Home = () => { +const Home = (props) => { + const { isLogged } = props; const homeTitle = { color: '#FFFFFF', @@ -84,6 +85,13 @@ const Home = () => { position: 'relative', }; + const disabledCard = { + ...baseCard, + opacity: 0.8, + cursor: 'not-allowed', + }; + + const logoImg = { width: '100%', height: '100%', @@ -148,31 +156,47 @@ const Home = () => {

Data Libraries in DUOS

-

Click the images below to view curated Data Libraries, and search and request access to data.

+

+ {isLogged + ? "Click the images below to view curated Data Libraries, and search and request access to data." + : "Login to view curated Data Libraries, and search and request access to data."} +

- - -
+ +
+ {isLogged ? ( + + AnVIL + + ) : ( AnVIL -
- + )} +
- - -
+ +
+ {isLogged ? ( + + Broad Institute + + ) : ( Broad Institute -
- + )} +
- - -
+ +
+ {isLogged ? ( + + Human Cell Atlas + + ) : ( Human Cell Atlas -
- + )} +
From d6ca5b15cb813b0ae73c3cce0a1c888271f377de Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Tue, 20 May 2025 11:57:19 -0400 Subject: [PATCH 7/8] feat: Update Tests --- cypress/component/Home/home.spec.jsx | 114 ++++++++++++++++++--------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/cypress/component/Home/home.spec.jsx b/cypress/component/Home/home.spec.jsx index e85b0a700..1103f6e6b 100644 --- a/cypress/component/Home/home.spec.jsx +++ b/cypress/component/Home/home.spec.jsx @@ -5,49 +5,85 @@ import { MemoryRouter } from 'react-router-dom'; import Home from '../../../src/pages/Home'; describe('Home Page - Tests', function() { - beforeEach(() => { - mount( - - - - ); - }); + describe('When user is not logged in', function() { + beforeEach(() => { + mount( + + + + ); + }); - it('renders the page header correctly', function() { - cy.contains('Data Use Oversight System').should('be.visible'); - cy.contains('Expediting compliant data sharing').should('be.visible'); - }); + it('renders the page header correctly', function() { + cy.contains('Data Use Oversight System').should('be.visible'); + cy.contains('Expediting compliant data sharing').should('be.visible'); + }); - it('renders the Data Libraries section with correct header', function() { - cy.contains('Data Libraries in DUOS').should('be.visible'); - cy.contains('Click the images below to view curated Data Libraries, and search and request access to data.') - .should('be.visible'); - }); + it('renders the Data Libraries section with login message', function() { + cy.contains('Data Libraries in DUOS').should('be.visible'); + cy.contains('Login to view curated Data Libraries').should('be.visible'); + }); - /** - * The native HTML title attribute creates a browser tooltip on hover, but these tooltips are not separate DOM elements - they're just a browser feature triggered by the attribute. That's why you don't see separate tooltip elements in the DOM. The test checks the presence of elements with the appropriate title attributes. - */ - it('displays tooltips with correct text for data libraries', function() { - cy.get('[data-for="anvil"]').find('span[title="AnVIL"]').should('exist'); - cy.get('[data-for="broad"]').find('span[title="Broad Institute"]').should('exist'); - cy.get('[data-for="hca"]').find('span[title="Human Cell Atlas"]').should('exist'); - }); + it('displays tooltips with login required message for data libraries', function() { + cy.get('[data-for="anvil"]').find('span[title="Please login to access AnVIL Data Library"]').should('exist'); + cy.get('[data-for="broad"]').find('span[title="Please login to access Broad Institute Data Library"]').should('exist'); + cy.get('[data-for="hca"]').find('span[title="Please login to access Human Cell Atlas Data Library"]').should('exist'); + }); - it('has correct navigation links for data libraries', function() { - cy.get('a[href="/datalibrary/anvil"]').should('exist'); - cy.get('a[href="/datalibrary/broad"]').should('exist'); - cy.get('a[href="/datalibrary/HCA"]').should('exist'); - }); - - it('displays logos horizontally on desktop', function() { - cy.viewport(1200, 800); - cy.get('.logo-grid').should('have.css', 'flex-direction', 'row'); - cy.get('.logo-card').should('have.length', 3); + it('does not have navigation links for data libraries', function() { + cy.get('a[href="/datalibrary/anvil"]').should('not.exist'); + cy.get('a[href="/datalibrary/broad"]').should('not.exist'); + cy.get('a[href="/datalibrary/HCA"]').should('not.exist'); + }); + + it('displays disabled logo cards', function() { + cy.get('.logo-card').should('have.length', 3); + cy.get('.logo-card').first().should('have.css', 'opacity', '0.8'); + cy.get('.logo-card').first().should('have.css', 'cursor', 'not-allowed'); + }); }); - - it('displays logos vertically on mobile', function() { - cy.viewport(600, 800); - cy.get('.logo-grid').should('have.css', 'flex-direction', 'column'); - cy.get('.logo-card').should('have.length', 3); + + describe('When user is logged in', function() { + beforeEach(() => { + mount( + + + + ); + }); + + it('renders the page header correctly', function() { + cy.contains('Data Use Oversight System').should('be.visible'); + cy.contains('Expediting compliant data sharing').should('be.visible'); + }); + + it('renders the Data Libraries section with clickable message', function() { + cy.contains('Data Libraries in DUOS').should('be.visible'); + cy.contains('Click the images below to view curated Data Libraries').should('be.visible'); + }); + + it('displays tooltips with correct text for data libraries', function() { + cy.get('[data-for="anvil"]').find('span[title="AnVIL"]').should('exist'); + cy.get('[data-for="broad"]').find('span[title="Broad Institute"]').should('exist'); + cy.get('[data-for="hca"]').find('span[title="Human Cell Atlas"]').should('exist'); + }); + + it('has correct navigation links for data libraries', function() { + cy.get('a[href="/datalibrary/anvil"]').should('exist'); + cy.get('a[href="/datalibrary/broad"]').should('exist'); + cy.get('a[href="/datalibrary/HCA"]').should('exist'); + }); + + it('displays logos horizontally on desktop', function() { + cy.viewport(1200, 800); + cy.get('.logo-grid').should('have.css', 'flex-direction', 'row'); + cy.get('.logo-card').should('have.length', 3); + }); + + it('displays logos vertically on mobile', function() { + cy.viewport(600, 800); + cy.get('.logo-grid').should('have.css', 'flex-direction', 'column'); + cy.get('.logo-card').should('have.length', 3); + }); }); }); \ No newline at end of file From 1997e33dd00797ae180edd5414688a63a586f128 Mon Sep 17 00:00:00 2001 From: PintoGideon Date: Wed, 21 May 2025 14:47:07 -0400 Subject: [PATCH 8/8] feat: Improve Data Library card navigation for unauthenticated users --- cypress/component/Home/home.spec.jsx | 50 ++++++++++++---- src/pages/Home.jsx | 90 ++++++++++++++++++---------- 2 files changed, 96 insertions(+), 44 deletions(-) diff --git a/cypress/component/Home/home.spec.jsx b/cypress/component/Home/home.spec.jsx index 1103f6e6b..b019921e1 100644 --- a/cypress/component/Home/home.spec.jsx +++ b/cypress/component/Home/home.spec.jsx @@ -19,9 +19,9 @@ describe('Home Page - Tests', function() { cy.contains('Expediting compliant data sharing').should('be.visible'); }); - it('renders the Data Libraries section with login message', function() { + it('renders the Data Libraries section with consistent message', function() { cy.contains('Data Libraries in DUOS').should('be.visible'); - cy.contains('Login to view curated Data Libraries').should('be.visible'); + cy.contains('Click the images below to view curated Data Libraries').should('be.visible'); }); it('displays tooltips with login required message for data libraries', function() { @@ -30,16 +30,34 @@ describe('Home Page - Tests', function() { cy.get('[data-for="hca"]').find('span[title="Please login to access Human Cell Atlas Data Library"]').should('exist'); }); - it('does not have navigation links for data libraries', function() { - cy.get('a[href="/datalibrary/anvil"]').should('not.exist'); - cy.get('a[href="/datalibrary/broad"]').should('not.exist'); - cy.get('a[href="/datalibrary/HCA"]').should('not.exist'); - }); - - it('displays disabled logo cards', function() { + it('interacts with library card links when not logged in', function() { cy.get('.logo-card').should('have.length', 3); - cy.get('.logo-card').first().should('have.css', 'opacity', '0.8'); - cy.get('.logo-card').first().should('have.css', 'cursor', 'not-allowed'); + cy.get('.logo-card').each($card => { + cy.wrap($card).find('a').should('exist'); + }); + + // Create a spy on replaceState to check if URL parameters are updated + cy.window().then((win) => { + cy.spy(win.history, 'replaceState').as('replaceState'); + }); + + // Stub document.querySelectorAll to simulate no sign-in button found (fallback case) + cy.window().then((win) => { + cy.stub(win.document, 'querySelectorAll').returns([]); + }); + + // Also stub scrollTo for the fallback behavior + cy.window().then((win) => { + cy.stub(win, 'scrollTo').as('scrollTo'); + }); + + cy.get('.logo-card').first().find('a').click({ force: true }); + + cy.get('@replaceState').should('be.called'); + cy.get('@scrollTo').should('be.called'); + + // URL should contain the redirectTo parameter + cy.location('search').should('include', 'redirectTo=%2Fdatalibrary%2Fanvil'); }); }); @@ -68,12 +86,20 @@ describe('Home Page - Tests', function() { cy.get('[data-for="hca"]').find('span[title="Human Cell Atlas"]').should('exist'); }); - it('has correct navigation links for data libraries', function() { + it('has direct navigation links when logged in', function() { cy.get('a[href="/datalibrary/anvil"]').should('exist'); cy.get('a[href="/datalibrary/broad"]').should('exist'); cy.get('a[href="/datalibrary/HCA"]').should('exist'); }); + it('navigates directly without calling handleSignIn when logged in', function() { + cy.window().then((win) => { + cy.spy(win.history, 'replaceState').as('replaceState'); + }); + cy.get('a[href="/datalibrary/anvil"]').click({ force: true }); + cy.get('@replaceState').should('not.be.called'); + }); + it('displays logos horizontally on desktop', function() { cy.viewport(1200, 800); cy.get('.logo-grid').should('have.css', 'flex-direction', 'row'); diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index ad19f0027..43fd80f35 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -85,13 +85,6 @@ const Home = (props) => { position: 'relative', }; - const disabledCard = { - ...baseCard, - opacity: 0.8, - cursor: 'not-allowed', - }; - - const logoImg = { width: '100%', height: '100%', @@ -99,6 +92,26 @@ const Home = (props) => { display: 'block', }; + const handleSignIn = (redirectPath) => { + // Set the redirectTo parameter without forcing a page reload + const currentUrl = new URL(window.location.href); + currentUrl.searchParams.set('redirectTo', redirectPath); + window.history.replaceState({}, '', currentUrl); + + // Find the existing sign-in button in the header and programmatically click it + // This will trigger the existing authentication flow with all proper session handling + const signInButtons = document.querySelectorAll('button'); + const signInButton = Array.from(signInButtons).find(button => + button.textContent && button.textContent.trim() === 'Sign In' + ); + if (signInButton) { + signInButton.click(); + } else { + // Fallback - scroll to top where the sign-in button is located + window.scrollTo({ top: 0, behavior: 'smooth' }); + } + }; + return ( <>