@openneuro/app 4.3.0-alpha.5 → 4.4.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/scripts/pages/import-dataset.tsx +60 -0
- package/src/scripts/refactor_2021/dataset/draft-container.tsx +1 -2
- package/src/scripts/refactor_2021/dataset/mutations/follow.tsx +1 -7
- package/src/scripts/refactor_2021/dataset/mutations/import-dataset.tsx +97 -0
- package/src/scripts/refactor_2021/dataset/mutations/star.tsx +1 -7
- package/src/scripts/refactor_2021/dataset/snapshot-container.tsx +2 -2
- package/src/scripts/refactor_2021/routes.tsx +2 -0
- package/src/scripts/refactor_2021/uploader/upload-disclaimer-input.tsx +87 -0
- package/src/scripts/refactor_2021/uploader/upload-disclaimer.jsx +19 -61
- package/src/scripts/refactor_2021/user-login-modal-ctx.tsx +2 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openneuro/app",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0-alpha.0",
|
|
4
4
|
"description": "React JS web frontend for the OpenNeuro platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "public/client.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"@elastic/apm-rum": "5.9.1",
|
|
20
20
|
"@emotion/react": "11.6.0",
|
|
21
21
|
"@emotion/styled": "11.6.0",
|
|
22
|
-
"@openneuro/client": "^4.
|
|
23
|
-
"@openneuro/components": "^4.
|
|
22
|
+
"@openneuro/client": "^4.4.0-alpha.0",
|
|
23
|
+
"@openneuro/components": "^4.4.0-alpha.0",
|
|
24
24
|
"babel-runtime": "^6.26.0",
|
|
25
25
|
"bids-validator": "1.8.8",
|
|
26
26
|
"bytes": "^3.0.0",
|
|
@@ -116,5 +116,5 @@
|
|
|
116
116
|
"publishConfig": {
|
|
117
117
|
"access": "public"
|
|
118
118
|
},
|
|
119
|
-
"gitHead": "
|
|
119
|
+
"gitHead": "732d5f59ef4723e6236974679eabe3cc9c3ad09f"
|
|
120
120
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import styled from '@emotion/styled'
|
|
3
|
+
import { ImportDatasetMutation } from '../refactor_2021/dataset/mutations/import-dataset'
|
|
4
|
+
import { useLocation } from 'react-router-dom'
|
|
5
|
+
import LoggedIn from '../refactor_2021/authentication/logged-in'
|
|
6
|
+
import LoggedOut from '../refactor_2021/authentication/logged-out'
|
|
7
|
+
import { testAffirmed } from '../refactor_2021/uploader/upload-disclaimer'
|
|
8
|
+
import { UploadDisclaimerInput } from '../refactor_2021/uploader/upload-disclaimer-input'
|
|
9
|
+
|
|
10
|
+
function useQuery() {
|
|
11
|
+
const { search } = useLocation()
|
|
12
|
+
return React.useMemo(() => new URLSearchParams(search), [search])
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const ImportDatasetPageStyle = styled.div`
|
|
16
|
+
background: white;
|
|
17
|
+
|
|
18
|
+
.container {
|
|
19
|
+
max-width: 60em;
|
|
20
|
+
min-height: calc(100vh - 125px);
|
|
21
|
+
}
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
export const ImportDataset: React.VoidFunctionComponent = () => {
|
|
25
|
+
const url = useQuery().get('url')
|
|
26
|
+
const [affirmedDefaced, setAffirmedDefaced] = useState(false)
|
|
27
|
+
const [affirmedConsent, setAffirmedConsent] = useState(false)
|
|
28
|
+
return (
|
|
29
|
+
<ImportDatasetPageStyle>
|
|
30
|
+
<div className="container">
|
|
31
|
+
<h2>Import a dataset from remote URL</h2>
|
|
32
|
+
<p>
|
|
33
|
+
Use this page to import a new OpenNeuro dataset from{' '}
|
|
34
|
+
<a href="https://brainlife.io/ezbids/">ezBIDS</a>. After submitting an
|
|
35
|
+
import, please allow some time for processing and you will receive an
|
|
36
|
+
email notification when complete.
|
|
37
|
+
</p>
|
|
38
|
+
<LoggedIn>
|
|
39
|
+
<UploadDisclaimerInput
|
|
40
|
+
affirmedDefaced={affirmedDefaced}
|
|
41
|
+
affirmedConsent={affirmedConsent}
|
|
42
|
+
onChange={({ affirmedDefaced, affirmedConsent }): void => {
|
|
43
|
+
setAffirmedDefaced(affirmedDefaced)
|
|
44
|
+
setAffirmedConsent(affirmedConsent)
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
<ImportDatasetMutation
|
|
48
|
+
url={url}
|
|
49
|
+
disabled={testAffirmed(affirmedDefaced, affirmedConsent)}
|
|
50
|
+
affirmedDefaced={affirmedDefaced}
|
|
51
|
+
affirmedConsent={affirmedConsent}
|
|
52
|
+
/>
|
|
53
|
+
</LoggedIn>
|
|
54
|
+
<LoggedOut>
|
|
55
|
+
<p>Please sign in to continue.</p>
|
|
56
|
+
</LoggedOut>
|
|
57
|
+
</div>
|
|
58
|
+
</ImportDatasetPageStyle>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -182,7 +182,6 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
|
|
|
182
182
|
<DatasetTools
|
|
183
183
|
hasEdit={hasEdit}
|
|
184
184
|
isPublic={dataset.public}
|
|
185
|
-
isSnapshot={isSnapshot}
|
|
186
185
|
datasetId={datasetId}
|
|
187
186
|
isAdmin={isAdmin}
|
|
188
187
|
hasSnapshot={dataset.snapshots.length !== 0}
|
|
@@ -236,7 +235,7 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
|
|
|
236
235
|
heading="Authors"
|
|
237
236
|
description={description.Authors}
|
|
238
237
|
editMode={hasEdit}>
|
|
239
|
-
{description
|
|
238
|
+
{description?.Authors?.length ? description.Authors : ['N/A']}
|
|
240
239
|
</EditDescriptionList>
|
|
241
240
|
|
|
242
241
|
{summary && (
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { FC, useContext } from 'react'
|
|
2
|
-
import { useLocation } from 'react-router-dom'
|
|
3
2
|
import { gql } from '@apollo/client'
|
|
4
3
|
import { Mutation } from '@apollo/client/react/components'
|
|
5
4
|
import { datasetCacheId } from '../../../datalad/mutations/cache-id.js'
|
|
@@ -45,16 +44,11 @@ export const FollowDataset: FC<FollowDatasetProps> = ({
|
|
|
45
44
|
profile,
|
|
46
45
|
followers,
|
|
47
46
|
}) => {
|
|
48
|
-
const { setUserModalOpen
|
|
49
|
-
const location = useLocation()
|
|
47
|
+
const { setUserModalOpen } = useContext(UserModalOpenCtx)
|
|
50
48
|
const handleToggle = followDataset => () => {
|
|
51
49
|
if (!profile) {
|
|
52
50
|
// if user is not logged in, give them the option to do so
|
|
53
51
|
// then redirect back to this page
|
|
54
|
-
setLoginOptions(prevState => ({
|
|
55
|
-
...prevState,
|
|
56
|
-
redirect: `${location.pathname}`,
|
|
57
|
-
}))
|
|
58
52
|
setUserModalOpen(true)
|
|
59
53
|
} else {
|
|
60
54
|
followDataset({ variables: { datasetId } })
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React, { FC, useState } from 'react'
|
|
2
|
+
import { gql, useMutation, useApolloClient } from '@apollo/client'
|
|
3
|
+
import { Button } from '@openneuro/components/button'
|
|
4
|
+
import { createDataset } from '../../uploader/upload-mutation'
|
|
5
|
+
import styled from '@emotion/styled'
|
|
6
|
+
|
|
7
|
+
export const IMPORT_DATASET = gql`
|
|
8
|
+
mutation importRemoteDataset($datasetId: ID!, $url: String!) {
|
|
9
|
+
importRemoteDataset(datasetId: $datasetId, url: $url)
|
|
10
|
+
}
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
const StatusRow = styled.div`
|
|
14
|
+
margin-top: 1em;
|
|
15
|
+
`
|
|
16
|
+
|
|
17
|
+
const URLInput = styled.input`
|
|
18
|
+
width: 100%;
|
|
19
|
+
`
|
|
20
|
+
|
|
21
|
+
interface ImportDatasetMutationProps {
|
|
22
|
+
url: string
|
|
23
|
+
affirmedDefaced: boolean
|
|
24
|
+
affirmedConsent: boolean
|
|
25
|
+
disabled?: boolean | null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const ImportDatasetMutation: FC<ImportDatasetMutationProps> = ({
|
|
29
|
+
url,
|
|
30
|
+
disabled,
|
|
31
|
+
affirmedDefaced,
|
|
32
|
+
affirmedConsent,
|
|
33
|
+
}) => {
|
|
34
|
+
const [importStarted, setImportStarted] = useState(false)
|
|
35
|
+
const [importFailed, setImportFailed] = useState(false)
|
|
36
|
+
const [ImportDataset] = useMutation(IMPORT_DATASET)
|
|
37
|
+
const apolloClient = useApolloClient()
|
|
38
|
+
|
|
39
|
+
let status = (
|
|
40
|
+
<Button
|
|
41
|
+
className="btn-modal-action"
|
|
42
|
+
primary={true}
|
|
43
|
+
label="Start Import"
|
|
44
|
+
size="medium"
|
|
45
|
+
disabled={disabled}
|
|
46
|
+
onClick={async () => {
|
|
47
|
+
const createDatasetMutation = createDataset(apolloClient)
|
|
48
|
+
const datasetId = await createDatasetMutation({
|
|
49
|
+
affirmedDefaced,
|
|
50
|
+
affirmedConsent,
|
|
51
|
+
})
|
|
52
|
+
try {
|
|
53
|
+
await ImportDataset({
|
|
54
|
+
variables: { datasetId, url },
|
|
55
|
+
})
|
|
56
|
+
setImportStarted(true)
|
|
57
|
+
} catch (err) {
|
|
58
|
+
setImportFailed(true)
|
|
59
|
+
}
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
// User can start import
|
|
65
|
+
|
|
66
|
+
// Import is running successfully
|
|
67
|
+
if (importStarted && !importFailed) {
|
|
68
|
+
status = (
|
|
69
|
+
<p>
|
|
70
|
+
This import has been started and you will receive an email when it is
|
|
71
|
+
complete.
|
|
72
|
+
</p>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (importFailed) {
|
|
77
|
+
status = (
|
|
78
|
+
<p>
|
|
79
|
+
An error was encountered importing this URL. This may indicate the URL
|
|
80
|
+
is inaccessible or is not the correct zip format. Please contact support
|
|
81
|
+
if you have verified the bundle is correct and still experience this
|
|
82
|
+
error.
|
|
83
|
+
</p>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<label>
|
|
90
|
+
Source URL
|
|
91
|
+
<URLInput type="text" disabled value={url} id="import-url" />
|
|
92
|
+
</label>
|
|
93
|
+
|
|
94
|
+
<StatusRow>{status}</StatusRow>
|
|
95
|
+
</>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { FC, useContext } from 'react'
|
|
2
|
-
import { useLocation } from 'react-router-dom'
|
|
3
2
|
import { gql } from '@apollo/client'
|
|
4
3
|
import { Mutation } from '@apollo/client/react/components'
|
|
5
4
|
import { datasetCacheId } from '../../../datalad/mutations/cache-id.js'
|
|
@@ -44,16 +43,11 @@ export const StarDataset: FC<StarDatasetProps> = ({
|
|
|
44
43
|
profile,
|
|
45
44
|
stars,
|
|
46
45
|
}) => {
|
|
47
|
-
const { setUserModalOpen
|
|
48
|
-
const location = useLocation()
|
|
46
|
+
const { setUserModalOpen } = useContext(UserModalOpenCtx)
|
|
49
47
|
const handleToggle = starDataset => () => {
|
|
50
48
|
if (!profile) {
|
|
51
49
|
// if user is not logged in, give them the option to do so
|
|
52
50
|
// then redirect back to this page
|
|
53
|
-
setLoginOptions(prevState => ({
|
|
54
|
-
...prevState,
|
|
55
|
-
redirect: `${location.pathname}`,
|
|
56
|
-
}))
|
|
57
51
|
setUserModalOpen(true)
|
|
58
52
|
} else {
|
|
59
53
|
starDataset({ variables: { datasetId } })
|
|
@@ -172,7 +172,7 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
172
172
|
hasEdit={hasEdit}
|
|
173
173
|
isPublic={dataset.public}
|
|
174
174
|
datasetId={datasetId}
|
|
175
|
-
|
|
175
|
+
snapshotId={snapshot.tag}
|
|
176
176
|
isAdmin={isAdmin}
|
|
177
177
|
isDatasetAdmin={isDatasetAdmin}
|
|
178
178
|
/>
|
|
@@ -214,7 +214,7 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
214
214
|
<MetaDataBlock
|
|
215
215
|
heading="Authors"
|
|
216
216
|
item={
|
|
217
|
-
description
|
|
217
|
+
description?.Authors?.length
|
|
218
218
|
? description.Authors.join(', ')
|
|
219
219
|
: 'N/A'
|
|
220
220
|
}
|
|
@@ -14,6 +14,7 @@ import ErrorRoute from '../errors/errorRoute'
|
|
|
14
14
|
import { PETRedirect } from '../pet/redirect'
|
|
15
15
|
import Citation from '../pages/citation-page'
|
|
16
16
|
import FourOFourPage from '../errors/404page'
|
|
17
|
+
import { ImportDataset } from '../pages/import-dataset'
|
|
17
18
|
|
|
18
19
|
const Routes: React.VoidFunctionComponent = () => (
|
|
19
20
|
<Switch>
|
|
@@ -26,6 +27,7 @@ const Routes: React.VoidFunctionComponent = () => (
|
|
|
26
27
|
<Route path="/error" component={ErrorRoute} />
|
|
27
28
|
<Route path="/pet" component={PETRedirect} />
|
|
28
29
|
<Route path="/cite" component={Citation} />
|
|
30
|
+
<Route path="/import" component={ImportDataset} />
|
|
29
31
|
<Redirect from="/public" to="/search" />
|
|
30
32
|
<Redirect from="/saved" to="/search?bookmarks" />
|
|
31
33
|
<Redirect from="/dashboard" to="/search?mydatasets" />
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import styled from '@emotion/styled'
|
|
3
|
+
|
|
4
|
+
interface UploadDisclaimerInputProps {
|
|
5
|
+
affirmedDefaced: boolean
|
|
6
|
+
affirmedConsent: boolean
|
|
7
|
+
onChange: ({
|
|
8
|
+
affirmedDefaced,
|
|
9
|
+
affirmedConsent,
|
|
10
|
+
}: {
|
|
11
|
+
affirmedDefaced: boolean
|
|
12
|
+
affirmedConsent: boolean
|
|
13
|
+
}) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const DisclaimerLabel = styled.label`
|
|
17
|
+
display: block;
|
|
18
|
+
font-weight: bold;
|
|
19
|
+
margin-bottom: 20px;
|
|
20
|
+
border-top: 1px solid;
|
|
21
|
+
padding-top: 10px;
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
export const UploadDisclaimerInput: React.FunctionComponent<UploadDisclaimerInputProps> =
|
|
25
|
+
({ affirmedDefaced, affirmedConsent, onChange }) => {
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<h4>
|
|
29
|
+
By uploading this dataset to OpenNeuro I agree to the following
|
|
30
|
+
conditions:
|
|
31
|
+
</h4>
|
|
32
|
+
<p>
|
|
33
|
+
I am the owner of this dataset and have any necessary ethics
|
|
34
|
+
permissions to share the data publicly. This dataset does not include
|
|
35
|
+
any identifiable personal health information as defined by the{' '}
|
|
36
|
+
<a href="https://www.hhs.gov/hipaa/for-professionals/privacy/laws-regulations/">
|
|
37
|
+
Health Insurance Portability and Accountability Act of 1996
|
|
38
|
+
</a>{' '}
|
|
39
|
+
(including names, zip codes, dates of birth, acquisition dates, etc).
|
|
40
|
+
I agree to destroy any key linking the personal identity of research
|
|
41
|
+
participants to the subject codes used in the dataset.
|
|
42
|
+
</p>
|
|
43
|
+
<p>
|
|
44
|
+
I agree that this dataset will become publicly available under a{' '}
|
|
45
|
+
<a href="https://wiki.creativecommons.org/wiki/CC0">
|
|
46
|
+
Creative Commons CC0
|
|
47
|
+
</a>{' '}
|
|
48
|
+
license after a grace period of 36 months counted from the date of the
|
|
49
|
+
first snapshot creation for this dataset. You will be able to apply
|
|
50
|
+
for up to two 6 month extensions to increase the grace period in case
|
|
51
|
+
the publication of a corresponding paper takes longer than expected.
|
|
52
|
+
See <a href="/faq">FAQ</a> for details.
|
|
53
|
+
</p>
|
|
54
|
+
<p>This dataset is not subject to GDPR protections.</p>
|
|
55
|
+
<p>
|
|
56
|
+
Generally, data should only be uploaded to a single data archive. In
|
|
57
|
+
the rare cases where it is necessary to upload the data to two
|
|
58
|
+
databases (such as the NIMH Data Archive), I agree to ensure that the
|
|
59
|
+
datasets are harmonized across archives.
|
|
60
|
+
</p>
|
|
61
|
+
<p>Please affirm one of the following:</p>
|
|
62
|
+
<DisclaimerLabel>
|
|
63
|
+
<input
|
|
64
|
+
type="checkbox"
|
|
65
|
+
onChange={(): void =>
|
|
66
|
+
onChange({ affirmedDefaced: !affirmedDefaced, affirmedConsent })
|
|
67
|
+
}
|
|
68
|
+
defaultChecked={affirmedDefaced}
|
|
69
|
+
/>
|
|
70
|
+
All structural scans have been defaced, obscuring any tissue on
|
|
71
|
+
or near the face that could potentially be used to reconstruct the
|
|
72
|
+
facial structure.
|
|
73
|
+
</DisclaimerLabel>
|
|
74
|
+
<DisclaimerLabel>
|
|
75
|
+
<input
|
|
76
|
+
type="checkbox"
|
|
77
|
+
onChange={(): void =>
|
|
78
|
+
onChange({ affirmedDefaced, affirmedConsent: !affirmedConsent })
|
|
79
|
+
}
|
|
80
|
+
defaultChecked={affirmedConsent}
|
|
81
|
+
/>
|
|
82
|
+
I have explicit participant consent and ethical authorization
|
|
83
|
+
to publish structural scans without defacing.
|
|
84
|
+
</DisclaimerLabel>
|
|
85
|
+
</>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import UploaderContext from './uploader-context.js'
|
|
3
|
+
import { UploadDisclaimerInput } from './upload-disclaimer-input'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Defacing/consent input logic
|
|
7
|
+
*/
|
|
8
|
+
export const testAffirmed = (affirmedDefaced, affirmedConsent) =>
|
|
9
|
+
!(
|
|
10
|
+
(affirmedDefaced && !affirmedConsent) ||
|
|
11
|
+
(!affirmedDefaced && affirmedConsent)
|
|
12
|
+
)
|
|
3
13
|
|
|
4
14
|
const UploadDisclaimer = () => {
|
|
5
15
|
const [affirmedDefaced, setAffirmedDefaced] = useState(false)
|
|
@@ -8,60 +18,14 @@ const UploadDisclaimer = () => {
|
|
|
8
18
|
<UploaderContext.Consumer>
|
|
9
19
|
{uploader => (
|
|
10
20
|
<div className="disclaimer fade-in">
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
the{' '}
|
|
20
|
-
<a href="https://www.hhs.gov/hipaa/for-professionals/privacy/laws-regulations/">
|
|
21
|
-
Health Insurance Portability and Accountability Act of 1996
|
|
22
|
-
</a>{' '}
|
|
23
|
-
(including names, zip codes, dates of birth, acquisition dates,
|
|
24
|
-
etc). I agree to destroy any key linking the personal identity of
|
|
25
|
-
research participants to the subject codes used in the dataset.
|
|
26
|
-
</p>
|
|
27
|
-
<p>
|
|
28
|
-
I agree that this dataset will become publicly available under a{' '}
|
|
29
|
-
<a href="https://wiki.creativecommons.org/wiki/CC0">
|
|
30
|
-
Creative Commons CC0
|
|
31
|
-
</a>{' '}
|
|
32
|
-
license after a grace period of 36 months counted from the date of
|
|
33
|
-
the first snapshot creation for this dataset. You will be able to
|
|
34
|
-
apply for up to two 6 month extensions to increase the grace period
|
|
35
|
-
in case the publication of a corresponding paper takes longer than
|
|
36
|
-
expected. See <a href="/faq">FAQ</a> for details.
|
|
37
|
-
</p>
|
|
38
|
-
<p>This dataset is not subject to GDPR protections.</p>
|
|
39
|
-
<p>
|
|
40
|
-
Generally, data should only be uploaded to a single data archive. In
|
|
41
|
-
the rare cases where it is necessary to upload the data to two
|
|
42
|
-
databases (such as the NIMH Data Archive), I agree to ensure that
|
|
43
|
-
the datasets are harmonized across archives.
|
|
44
|
-
</p>
|
|
45
|
-
<p>Please affirm one of the following:</p>
|
|
46
|
-
<label>
|
|
47
|
-
<input
|
|
48
|
-
type="checkbox"
|
|
49
|
-
onChange={() => setAffirmedDefaced(!affirmedDefaced)}
|
|
50
|
-
defaultChecked={affirmedDefaced}
|
|
51
|
-
/>
|
|
52
|
-
All structural scans have been defaced, obscuring any tissue
|
|
53
|
-
on or near the face that could potentially be used to reconstruct
|
|
54
|
-
the facial structure.
|
|
55
|
-
</label>
|
|
56
|
-
<label>
|
|
57
|
-
<input
|
|
58
|
-
type="checkbox"
|
|
59
|
-
onChange={() => setAffirmedConsent(!affirmedConsent)}
|
|
60
|
-
defaultChecked={affirmedConsent}
|
|
61
|
-
/>
|
|
62
|
-
I have explicit participant consent and ethical authorization
|
|
63
|
-
to publish structural scans without defacing.
|
|
64
|
-
</label>
|
|
21
|
+
<UploadDisclaimerInput
|
|
22
|
+
affirmedDefaced={affirmedDefaced}
|
|
23
|
+
affirmedConsent={affirmedConsent}
|
|
24
|
+
onChange={({ affirmedDefaced, affirmedConsent }) => {
|
|
25
|
+
setAffirmedDefaced(affirmedDefaced)
|
|
26
|
+
setAffirmedConsent(affirmedConsent)
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
65
29
|
<span className="message">
|
|
66
30
|
<button
|
|
67
31
|
className="fileupload-btn btn-blue"
|
|
@@ -73,13 +37,7 @@ const UploadDisclaimer = () => {
|
|
|
73
37
|
})
|
|
74
38
|
uploader.upload({ affirmedDefaced, affirmedConsent })
|
|
75
39
|
}}
|
|
76
|
-
disabled={
|
|
77
|
-
!(
|
|
78
|
-
(affirmedDefaced && !affirmedConsent) ||
|
|
79
|
-
(!affirmedDefaced && affirmedConsent)
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
>
|
|
40
|
+
disabled={testAffirmed(affirmedDefaced, affirmedConsent)}>
|
|
83
41
|
I Agree
|
|
84
42
|
</button>
|
|
85
43
|
</span>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { createContext, useState, FC, ReactNode } from 'react'
|
|
2
2
|
import { UserLoginModal } from '@openneuro/components/modal'
|
|
3
3
|
import loginUrls from './authentication/loginUrls'
|
|
4
|
+
import { useLocation } from 'react-router-dom'
|
|
4
5
|
|
|
5
6
|
export const UserModalOpenCtx = createContext(null)
|
|
6
7
|
|
|
@@ -12,20 +13,16 @@ export const UserModalOpenProvider: FC<UserModalOpenProviderProps> = ({
|
|
|
12
13
|
children,
|
|
13
14
|
}) => {
|
|
14
15
|
const [userModalOpen, setUserModalOpen] = useState(false)
|
|
15
|
-
const [loginOptions, setLoginOptions] = useState({
|
|
16
|
-
redirect: null
|
|
17
|
-
})
|
|
18
16
|
const toggle = (): void => {
|
|
19
17
|
setUserModalOpen(prevState => !prevState)
|
|
20
18
|
}
|
|
21
19
|
return (
|
|
22
|
-
<UserModalOpenCtx.Provider value={{ userModalOpen, setUserModalOpen
|
|
20
|
+
<UserModalOpenCtx.Provider value={{ userModalOpen, setUserModalOpen }}>
|
|
23
21
|
{children}
|
|
24
22
|
<UserLoginModal
|
|
25
23
|
isOpen={userModalOpen}
|
|
26
24
|
toggle={toggle}
|
|
27
25
|
loginUrls={loginUrls}
|
|
28
|
-
redirectPathParam={loginOptions.redirect}
|
|
29
26
|
/>
|
|
30
27
|
</UserModalOpenCtx.Provider>
|
|
31
28
|
)
|