@openneuro/app 4.4.8 → 4.5.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.
Files changed (42) hide show
  1. package/package.json +5 -5
  2. package/src/scripts/app.tsx +1 -1
  3. package/src/scripts/common/partials/papaya.jsx +1 -0
  4. package/src/scripts/index.tsx +1 -1
  5. package/src/scripts/{refactor_2021 → pages}/admin/admin.jsx +1 -1
  6. package/src/scripts/{refactor_2021 → pages}/admin/flagged-files.jsx +0 -0
  7. package/src/scripts/{refactor_2021 → pages}/admin/user-fragment.ts +0 -0
  8. package/src/scripts/{refactor_2021 → pages}/admin/user-tools.tsx +1 -1
  9. package/src/scripts/{refactor_2021 → pages}/admin/users.jsx +0 -0
  10. package/src/scripts/pages/citation-page.tsx +1 -1
  11. package/src/scripts/{front-page → pages/front-page}/front-page-content.ts +10 -10
  12. package/src/scripts/{refactor_2021/containers/front-page-container.tsx → pages/front-page/front-page.tsx} +53 -32
  13. package/src/scripts/pages/front-page-comp.tsx +57 -0
  14. package/src/scripts/{pet/redirect.tsx → pages/pet-redirect.tsx} +0 -0
  15. package/src/scripts/refactor_2021/dataset/draft-container.tsx +303 -318
  16. package/src/scripts/refactor_2021/dataset/files/file-viewer-type.jsx +2 -0
  17. package/src/scripts/refactor_2021/dataset/fragments/__tests__/doi-link.spec.tsx +38 -8
  18. package/src/scripts/refactor_2021/dataset/fragments/doi-link.tsx +9 -6
  19. package/src/scripts/refactor_2021/dataset/mutations/dataset-relations.tsx +2 -3
  20. package/src/scripts/refactor_2021/dataset/snapshot-container.tsx +98 -112
  21. package/src/scripts/refactor_2021/uploader/upload-issues.jsx +1 -0
  22. package/src/scripts/{refactor_2021/routes.tsx → routes.tsx} +10 -10
  23. package/src/scripts/front-page/assets/get_data_browse.png +0 -0
  24. package/src/scripts/front-page/assets/get_data_download.png +0 -0
  25. package/src/scripts/front-page/assets/ljaf.png +0 -0
  26. package/src/scripts/front-page/assets/logo_app.png +0 -0
  27. package/src/scripts/front-page/assets/logo_cube.png +0 -0
  28. package/src/scripts/front-page/assets/logo_data.png +0 -0
  29. package/src/scripts/front-page/assets/logo_users.png +0 -0
  30. package/src/scripts/front-page/assets/nih.png +0 -0
  31. package/src/scripts/front-page/assets/nsf.png +0 -0
  32. package/src/scripts/front-page/assets/share_data_collaborate.png +0 -0
  33. package/src/scripts/front-page/assets/share_data_publish.png +0 -0
  34. package/src/scripts/front-page/assets/share_data_validate.png +0 -0
  35. package/src/scripts/front-page/assets/squishymedia.png +0 -0
  36. package/src/scripts/front-page/assets/stanford.png +0 -0
  37. package/src/scripts/front-page/assets/tab-get_data.png +0 -0
  38. package/src/scripts/front-page/assets/tab-share_data.png +0 -0
  39. package/src/scripts/front-page/assets/tab-use_data.png +0 -0
  40. package/src/scripts/front-page/assets/use_data_analyze.png +0 -0
  41. package/src/scripts/front-page/assets/use_data_snapshot.png +0 -0
  42. package/src/scripts/mobile/collapsible-wrapper.tsx +0 -93
@@ -14,6 +14,8 @@ const FileViewerType = ({ path, url, data }) => {
14
14
  if (
15
15
  path.endsWith('README') ||
16
16
  path.endsWith('CHANGES') ||
17
+ path.endsWith('.bidsignore') ||
18
+ path.endsWith('.gitignore') ||
17
19
  path.endsWith('.txt')
18
20
  ) {
19
21
  return <FileViewerText data={data} />
@@ -5,9 +5,12 @@ import { MemoryRouter } from 'react-router-dom'
5
5
 
6
6
  describe('DoiLink component', () => {
7
7
  it('Renders usable link with raw DOI value', () => {
8
- render(<DOILink DOI="10.18112/openneuro.ds000001.v1.0.0" />, {
9
- wrapper: MemoryRouter,
10
- })
8
+ render(
9
+ <DOILink DOI="10.18112/openneuro.ds000001.v1.0.0" datasetId="ds000001" />,
10
+ {
11
+ wrapper: MemoryRouter,
12
+ },
13
+ )
11
14
  expect(screen.getByRole('link')).toHaveTextContent(
12
15
  'doi:10.18112/openneuro.ds000001.v1.0.0',
13
16
  )
@@ -17,26 +20,53 @@ describe('DoiLink component', () => {
17
20
  )
18
21
  })
19
22
  it('Renders usable link with URI DOI value', () => {
20
- render(<DOILink DOI="doi:10.18112/openneuro.ds000001.v1.0.0" />, {
21
- wrapper: MemoryRouter,
22
- })
23
+ render(
24
+ <DOILink
25
+ DOI="doi:10.18112/openneuro.ds000001.v1.0.0"
26
+ datasetId="ds000001"
27
+ />,
28
+ {
29
+ wrapper: MemoryRouter,
30
+ },
31
+ )
23
32
  expect(screen.getByRole('link')).toHaveTextContent(
24
33
  'doi:10.18112/openneuro.ds000001.v1.0.0',
25
34
  )
26
35
  })
27
36
  it('Renders usage link with URL DOI value', () => {
28
37
  render(
29
- <DOILink DOI="https://doi.org/10.18112/openneuro.ds000001.v1.0.0" />,
38
+ <DOILink
39
+ DOI="https://doi.org/10.18112/openneuro.ds000001.v1.0.0"
40
+ datasetId="ds000001"
41
+ />,
30
42
  { wrapper: MemoryRouter },
31
43
  )
32
44
  expect(screen.getByRole('link')).toHaveTextContent(
33
45
  'doi:10.18112/openneuro.ds000001.v1.0.0',
34
46
  )
35
47
  })
48
+ it('Renders fallback link with invalid DOI value', () => {
49
+ render(<DOILink DOI="doi:x" datasetId="ds000001" />, {
50
+ wrapper: MemoryRouter,
51
+ })
52
+ expect(screen.getByRole('link')).toHaveTextContent(
53
+ 'Create a new snapshot to obtain a DOI for the snapshot.',
54
+ )
55
+ expect(screen.getByRole('link')).toHaveAttribute(
56
+ 'href',
57
+ '/datasets/ds000001/snapshot',
58
+ )
59
+ })
36
60
  it('Renders fallback text if no valid DOI string is found', () => {
37
- render(<DOILink DOI={null} />, { wrapper: MemoryRouter })
61
+ render(<DOILink DOI={null} datasetId="ds000001" />, {
62
+ wrapper: MemoryRouter,
63
+ })
38
64
  expect(screen.getByRole('link')).toHaveTextContent(
39
65
  'Create a new snapshot to obtain a DOI for the snapshot.',
40
66
  )
67
+ expect(screen.getByRole('link')).toHaveAttribute(
68
+ 'href',
69
+ '/datasets/ds000001/snapshot',
70
+ )
41
71
  })
42
72
  })
@@ -4,7 +4,13 @@ import { Link } from 'react-router-dom'
4
4
  // See https://www.crossref.org/blog/dois-and-matching-regular-expressions/
5
5
  export const DOIPattern = /^10.\d{4,9}\/[-._;()/:A-Z0-9]+$/i
6
6
 
7
- export const DOILink = ({ DOI }) => {
7
+ export const DOILinkFallback = ({ datasetId }) => (
8
+ <Link to={`/datasets/${datasetId}/snapshot`}>
9
+ Create a new snapshot to obtain a DOI for the snapshot.
10
+ </Link>
11
+ )
12
+
13
+ export const DOILink = ({ DOI, datasetId }) => {
8
14
  if (
9
15
  DOI &&
10
16
  (DOI.match(DOIPattern) ||
@@ -20,11 +26,8 @@ export const DOILink = ({ DOI }) => {
20
26
  if (DOI.startsWith('https://doi.org/')) {
21
27
  return <a href={DOI}>{`doi:${DOI.slice(16)}`}</a>
22
28
  }
29
+ return <DOILinkFallback datasetId={datasetId} />
23
30
  } else {
24
- return (
25
- <Link to="snapshot">
26
- Create a new snapshot to obtain a DOI for the snapshot.
27
- </Link>
28
- )
31
+ return <DOILinkFallback datasetId={datasetId} />
29
32
  }
30
33
  }
@@ -96,7 +96,7 @@ export const DatasetRelations = ({ datasetId, hasEdit }) => {
96
96
  return (
97
97
  <React.Fragment key={obj.id}>
98
98
  <GridItem>
99
- <DOILink DOI={obj.id} />
99
+ <DOILink DOI={obj.id} datasetId={datasetId} />
100
100
  </GridItem>
101
101
  <GridItem>{obj.description}</GridItem>
102
102
  <GridItem>
@@ -107,8 +107,7 @@ export const DatasetRelations = ({ datasetId, hasEdit }) => {
107
107
  variables: { datasetId, doi: obj.id },
108
108
  })
109
109
  await refetch()
110
- }}
111
- >
110
+ }}>
112
111
  Delete
113
112
  </button>
114
113
  </GridItem>
@@ -22,7 +22,6 @@ import {
22
22
  CloneDropdown,
23
23
  DatasetHeader,
24
24
  DatasetHeaderMeta,
25
- DatasetPage,
26
25
  DatasetGitAccess,
27
26
  VersionList,
28
27
  DatasetTools,
@@ -88,35 +87,28 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
88
87
  hasEditPermissions(dataset.permissions, profile?.sub) || isAdmin
89
88
  const isDatasetAdmin =
90
89
  hasDatasetAdminPermissions(dataset.permissions, profile?.sub) || isAdmin
90
+ const modality: string = summary?.modalities[0] || ''
91
91
 
92
92
  return (
93
- <>
94
- <DatasetPage
95
- modality={summary?.modalities[0]}
96
- renderHeader={() => (
97
- <>
98
- {summary && (
99
- <DatasetHeader
100
- pageHeading={description.Name}
101
- modality={summary?.modalities[0]}
102
- />
103
- )}
104
- </>
105
- )}
106
- renderAlert={() => (
107
- <>
108
- {snapshot?.deprecated && (
109
- <DatasetAlertVersion
110
- datasetId={dataset.id}
111
- tag={snapshot.tag}
112
- reason={snapshot.deprecated.reason}
113
- hasEdit={hasEdit}
114
- />
115
- )}
116
- </>
117
- )}
118
- renderHeaderMeta={() => (
119
- <>
93
+ <div
94
+ className={`dataset dataset-draft dataset-page dataset-page-${modality?.toLowerCase()}`}>
95
+ {summary && (
96
+ <DatasetHeader
97
+ pageHeading={description.Name}
98
+ modality={summary?.modalities[0]}
99
+ />
100
+ )}
101
+ {snapshot?.deprecated && (
102
+ <DatasetAlertVersion
103
+ datasetId={dataset.id}
104
+ tag={snapshot.tag}
105
+ reason={snapshot.deprecated.reason}
106
+ hasEdit={hasEdit}
107
+ />
108
+ )}
109
+ <div className="container">
110
+ <div className="grid grid-between dataset-header-meta">
111
+ <div className="col col-8 col-lg">
120
112
  {summary && (
121
113
  <DatasetHeaderMeta
122
114
  size={summary.size}
@@ -124,10 +116,8 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
124
116
  datasetId={datasetId}
125
117
  />
126
118
  )}
127
- </>
128
- )}
129
- renderFollowBookmark={() => (
130
- <>
119
+ </div>
120
+ <div className="col follow-bookmark">
131
121
  <FollowDataset
132
122
  profile={profile}
133
123
  datasetId={dataset.id}
@@ -140,78 +130,79 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
140
130
  starred={dataset.starred}
141
131
  stars={dataset.stars.length}
142
132
  />
143
- </>
144
- )}
145
- renderBrainLifeButton={() => (
146
- <BrainLifeButton
147
- datasetId={datasetId}
148
- onBrainlife={snapshot.onBrainlife}
149
- snapshotVersion={snapshot.tag}
150
- />
151
- )}
152
- renderValidationBlock={() => (
153
- <ValidationBlock>
154
- <Validation datasetId={dataset.id} issues={snapshot.issues} />
155
- </ValidationBlock>
156
- )}
157
- renderCloneDropdown={() => (
158
- <CloneDropdown
159
- gitAccess={
160
- <DatasetGitAccess
133
+ </div>
134
+ </div>
135
+ </div>
136
+ <div className="container">
137
+ <div className="grid grid-between">
138
+ <div className="col col-lg col-8">
139
+ <div className="dataset-validation">
140
+ <ValidationBlock>
141
+ <Validation datasetId={dataset.id} issues={snapshot.issues} />
142
+ </ValidationBlock>
143
+ <BrainLifeButton
144
+ datasetId={datasetId}
145
+ onBrainlife={snapshot.onBrainlife}
146
+ snapshotVersion={snapshot.tag}
147
+ />
148
+ <CloneDropdown
149
+ gitAccess={
150
+ <DatasetGitAccess
151
+ hasEdit={hasEdit}
152
+ configGithub={config.github}
153
+ configUrl={config.url}
154
+ worker={dataset.worker}
155
+ datasetId={datasetId}
156
+ gitHash={snapshot.hexsha}
157
+ />
158
+ }
159
+ />
160
+ </div>
161
+ <div className="dataset-tool-buttons">
162
+ <DatasetTools
161
163
  hasEdit={hasEdit}
162
- configGithub={config.github}
163
- configUrl={config.url}
164
- worker={dataset.worker}
164
+ isPublic={dataset.public}
165
165
  datasetId={datasetId}
166
- gitHash={snapshot.hexsha}
166
+ snapshotId={snapshot.tag}
167
+ isAdmin={isAdmin}
168
+ isDatasetAdmin={isDatasetAdmin}
167
169
  />
168
- }
169
- />
170
- )}
171
- renderToolButtons={() => (
172
- <DatasetTools
173
- hasEdit={hasEdit}
174
- isPublic={dataset.public}
175
- datasetId={datasetId}
176
- snapshotId={snapshot.tag}
177
- isAdmin={isAdmin}
178
- isDatasetAdmin={isDatasetAdmin}
179
- />
180
- )}
181
- renderFiles={() => (
182
- <ReadMore
183
- fileTree={true}
184
- id="collapse-tree"
185
- expandLabel="Read More"
186
- collapseLabel="Collapse">
187
- <Files
188
- datasetId={datasetId}
189
- snapshotTag={snapshot.tag}
190
- datasetName={description.Name}
191
- files={snapshot.files}
192
- editMode={false}
193
- datasetPermissions={dataset.permissions}
170
+ </div>
171
+ <ReadMore
172
+ fileTree={true}
173
+ id="collapse-tree"
174
+ expandLabel="Read More"
175
+ collapseLabel="Collapse">
176
+ <Files
177
+ datasetId={datasetId}
178
+ snapshotTag={snapshot.tag}
179
+ datasetName={description.Name}
180
+ files={snapshot.files}
181
+ editMode={false}
182
+ datasetPermissions={dataset.permissions}
183
+ />
184
+ </ReadMore>
185
+ <MetaDataBlock
186
+ heading="README"
187
+ item={
188
+ <ReadMore
189
+ id="readme"
190
+ expandLabel="Read More"
191
+ collapseLabel="Collapse">
192
+ <Markdown>
193
+ {snapshot.readme == null ? 'N/A' : snapshot.readme}
194
+ </Markdown>
195
+ </ReadMore>
196
+ }
197
+ className="dataset-readme markdown-body"
198
+ />
199
+ <Comments
200
+ datasetId={dataset.id}
201
+ uploader={dataset.uploader}
202
+ comments={dataset.comments}
194
203
  />
195
- </ReadMore>
196
- )}
197
- renderReadMe={() => (
198
- <MetaDataBlock
199
- heading="README"
200
- item={
201
- <ReadMore
202
- id="readme"
203
- expandLabel="Read More"
204
- collapseLabel="Collapse">
205
- <Markdown>
206
- {snapshot.readme == null ? 'N/A' : snapshot.readme}
207
- </Markdown>
208
- </ReadMore>
209
- }
210
- className="dataset-readme markdown-body"
211
- />
212
- )}
213
- renderSidebar={() => (
214
- <>
204
+ </div>
205
+ <div className="col sidebar">
215
206
  <MetaDataBlock
216
207
  heading="Authors"
217
208
  item={
@@ -337,7 +328,9 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
337
328
 
338
329
  <MetaDataBlock
339
330
  heading="Dataset DOI"
340
- item={<DOILink DOI={description.DatasetDOI} />}
331
+ item={
332
+ <DOILink DOI={description.DatasetDOI} datasetId={datasetId} />
333
+ }
341
334
  />
342
335
  <MetaDataBlock heading="License" item={description.License} />
343
336
 
@@ -378,17 +371,10 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
378
371
  item={description.EthicsApprovals}
379
372
  className="dmb-list"
380
373
  />
381
- </>
382
- )}
383
- renderComments={() => (
384
- <Comments
385
- datasetId={dataset.id}
386
- uploader={dataset.uploader}
387
- comments={dataset.comments}
388
- />
389
- )}
390
- />
391
- </>
374
+ </div>
375
+ </div>
376
+ </div>
377
+ </div>
392
378
  )
393
379
  }
394
380
 
@@ -67,6 +67,7 @@ class UploadValidator extends React.Component {
67
67
  config: {
68
68
  error: ['NO_AUTHORS'],
69
69
  ignoreSubjectConsistency: true,
70
+ blacklistModalities: ['Microscopy'],
70
71
  },
71
72
  }
72
73
  validate(this.props.files, options).then(this.done)
@@ -2,19 +2,19 @@ import React from 'react'
2
2
  import { Route, Switch, Redirect } from 'react-router-dom'
3
3
 
4
4
  // TODO - Re-enable code splitting these when we can
5
- import Dataset from './dataset/draft-snapshot-routes'
5
+ import Dataset from './refactor_2021/dataset/draft-snapshot-routes'
6
6
  //import PreRefactorDatasetProps from './dataset/dataset-pre-refactor-container'
7
7
 
8
8
  import { FAQS } from '@openneuro/components/faqs'
9
- import FrontPageContainer from './containers/front-page-container'
10
- import Admin from './admin/admin'
11
- import SearchRoutes from './search/search-routes'
12
- import APIKey from './user/api'
13
- import ErrorRoute from '../errors/errorRoute'
14
- import { PETRedirect } from '../pet/redirect'
15
- import Citation from '../pages/citation-page'
16
- import FourOFourPage from '../errors/404page'
17
- import { ImportDataset } from '../pages/import-dataset'
9
+ import FrontPageContainer from './pages/front-page/front-page'
10
+ import Admin from './pages/admin/admin'
11
+ import SearchRoutes from './refactor_2021/search/search-routes'
12
+ import APIKey from './refactor_2021/user/api'
13
+ import ErrorRoute from './errors/errorRoute'
14
+ import { PETRedirect } from './pages/pet-redirect'
15
+ import Citation from './pages/citation-page'
16
+ import FourOFourPage from './errors/404page'
17
+ import { ImportDataset } from './pages/import-dataset'
18
18
 
19
19
  const Routes: React.VoidFunctionComponent = () => (
20
20
  <Switch>
@@ -1,93 +0,0 @@
1
- import React, { useState } from 'react'
2
- import PropTypes from 'prop-types'
3
- import styled from '@emotion/styled'
4
-
5
- interface IsOpenProps {
6
- isOpen: boolean
7
- }
8
-
9
- // wrapper for collapsible content on mobile
10
- const Content = styled.div<IsOpenProps>`
11
- height: 7em;
12
- overflow: hidden;
13
- text-align: left;
14
- ${(props): string =>
15
- props.isOpen &&
16
- `
17
- display: block;
18
- height: auto;
19
- overflow: auto;
20
- `};
21
- `
22
-
23
- const Collapse = ({ children, isOpen }): React.ReactElement => {
24
- return <Content isOpen={isOpen}>{children}</Content>
25
- }
26
-
27
- Collapse.propTypes = {
28
- children: PropTypes.node.isRequired,
29
- isOpen: PropTypes.bool,
30
- }
31
-
32
- Collapse.defaultProps = {
33
- isOpen: undefined,
34
- }
35
-
36
- const Item = styled.button`
37
- background-color: transparent;
38
- border: 0;
39
- font-weight: 700;
40
- padding: 0;
41
- &,
42
- &:hover {
43
- text-decoration: none;
44
- }
45
- &:focus {
46
- outline: 0;
47
- }
48
- `
49
-
50
- const Wrapper = styled.span`
51
- display: flex;
52
- align-items: center;
53
- `
54
-
55
- const Title = styled.p`
56
- padding-right: 0.5rem;
57
- cursor: pointer;
58
- color: #00505c;
59
- text-decoration: none;
60
- font-family: 'Cabin', sans-serif;
61
- font-size: 12px;
62
- `
63
-
64
- const Collapsible = ({ children, ...otherProps }): React.ReactElement => {
65
- const [isOpen, setOpen] = useState(false)
66
- const toggleItem = (): void => {
67
- setOpen(prevState => !prevState)
68
- }
69
- return (
70
- <>
71
- <div>
72
- <Collapse isOpen={isOpen}>{children}</Collapse>
73
- </div>
74
- <Item onClick={toggleItem}>
75
- <Wrapper>
76
- <Title>{!isOpen ? otherProps.title[0] : otherProps.title[1]}</Title>
77
- </Wrapper>
78
- </Item>
79
- </>
80
- )
81
- }
82
-
83
- Collapsible.propTypes = {
84
- children: PropTypes.node.isRequired,
85
- isOpen: PropTypes.bool,
86
- }
87
-
88
- Collapsible.defaultProps = {
89
- icon: 'down-chevron',
90
- isOpen: false,
91
- }
92
-
93
- export default Collapsible