Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clickthrough agreement for downloads #2947

Merged
merged 13 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions packages/openneuro-app/src/scripts/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { Cookies, CookiesProvider } from "react-cookie"
import { ToastContainer } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"
import { MediaContextProvider } from "./styles/media"
import { Agreement } from "./components/agreement"
import { LocalStorageProvider } from "./utils/local-storage"
import "./scss/index.scss"

interface AppProps {
children: ReactNode
Expand All @@ -19,16 +22,19 @@ const App: FC<AppProps> = ({
children: ReactNode
}) => {
return (
<CookiesProvider cookies={cookies}>
<MediaContextProvider>
<Helmet>
<title>{frontPage.pageTitle}</title>
<meta name="description" content={frontPage.pageDescription} />
</Helmet>
{children}
<ToastContainer position="bottom-right" />
</MediaContextProvider>
</CookiesProvider>
<LocalStorageProvider defaultValue={{ agreement: false }}>
<CookiesProvider cookies={cookies}>
<MediaContextProvider>
<Helmet>
<title>{frontPage.pageTitle}</title>
<meta name="description" content={frontPage.pageDescription} />
</Helmet>
{children}
<Agreement />
<ToastContainer position="bottom-right" />
</MediaContextProvider>
</CookiesProvider>
</LocalStorageProvider>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react"
import { fireEvent, render, screen } from "@testing-library/react"
import { Agreement } from "../agreement"
import { LocalStorageProvider } from "../../utils/local-storage"

describe("Agreement component", () => {
beforeEach(() => {
localStorage.clear()
})
afterEach(() => {
localStorage.clear()
})
it("Accepting the agreement sets the 'agreement' property in localStorage", () => {
render(
<LocalStorageProvider defaultValue={{}}>
<Agreement />
</LocalStorageProvider>,
)
fireEvent.click(screen.getByRole("button"))
expect(JSON.parse(localStorage.getItem("openneuro")).agreement).toEqual(
true,
)
})
})
74 changes: 74 additions & 0 deletions packages/openneuro-app/src/scripts/components/agreement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react"
import { useLocalStorage } from "../utils/local-storage"
import styled from "@emotion/styled"

export const STORAGE_KEY = "agreement"

const AgreementDiv = styled.div`
overflow: hidden;
position: fixed;
bottom: 0;
width: 100%;
background: white;
z-index: 1005;
-webkit-box-shadow: 0px -4px 3px rgba(50, 50, 50, 0.5);
-moz-box-shadow: 0px -4px 3px rgba(50, 50, 50, 0.5);
box-shadow: 0px -4px 3px rgba(50, 50, 50, 0.5);
padding: 4px;
`

const AgreementButton = styled.div`
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`

/**
* Hook to use the download agreement state from localStorage
*/
export function useAgreement() {
return useLocalStorage(STORAGE_KEY)
}

/**
* Floating agreement for data use that is only present if the user has not accepted this
*/
export const Agreement = () => {
const [agreed, setAgreed] = useAgreement()

if (agreed) {
return null
} else {
return (
<AgreementDiv>
<div className="container">
<div className="grid grid-between">
<div className="col col-lg col-11">
<p>
By clicking "I Agree", I affirm that I have the appropriate
institutional permissions to receive de-identified data for
secondary data analysis, and that neither I nor my collaborators
will attempt to reidentify individuals whose data are contained
in downloads from OpenNeuro. Further, if for any reason the
identity of participants contained in downloads from OpenNeuro
become known to me I will make no effort to recontact such
participants and will provide immediate notice to OpenNeuro
staff.
</p>
</div>
<div className="col col-lg col-1">
<AgreementButton
className="on-button on-button--small on-button--primary"
onClick={() => setAgreed(true)}
role="button"
>
I&nbsp;Agree
</AgreementButton>
</div>
</div>
</div>
</AgreementDiv>
)
}
}
Loading