@openneuro/app 4.8.2 → 4.9.1

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.
@@ -0,0 +1,29 @@
1
+ import React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import Helmet from 'react-helmet'
4
+ import '@testing-library/jest-dom/extend-expect'
5
+ import { SnapshotContainer } from '../snapshot-container'
6
+ import { MockAppWrapper } from '../../fixtures/mock-app-wrapper'
7
+ import { dataset, snapshot } from '../../fixtures/dataset-query'
8
+
9
+ const defProps = {
10
+ dataset,
11
+ snapshot,
12
+ tag: '1.0.0',
13
+ }
14
+
15
+ describe('SnapshotContainer component', () => {
16
+ it('renders successfully', () => {
17
+ const { asFragment } = render(<SnapshotContainer {...defProps} />, {
18
+ wrapper: MockAppWrapper,
19
+ })
20
+ expect(asFragment()).toMatchSnapshot()
21
+ })
22
+ it('includes JSON-LD data in the header', () => {
23
+ render(<SnapshotContainer {...defProps} />, {
24
+ wrapper: MockAppWrapper,
25
+ })
26
+ const header = Helmet.peek()
27
+ expect(header).toMatchSnapshot()
28
+ })
29
+ })
@@ -0,0 +1,12 @@
1
+ import styled from '@emotion/styled'
2
+
3
+ export const FollowToggles = styled.div`
4
+ display: flex;
5
+ font-size: 14px;
6
+ margin-left: auto;
7
+
8
+ .toggle-counter-wrap {
9
+ display: inline-flex;
10
+ margin-left: 1ch;
11
+ }
12
+ `
@@ -24,7 +24,6 @@ import {
24
24
  ValidationBlock,
25
25
  CloneDropdown,
26
26
  DatasetHeader,
27
- DatasetHeaderMeta,
28
27
  DatasetGitAccess,
29
28
  VersionList,
30
29
  DatasetTools,
@@ -38,6 +37,7 @@ import EditDescriptionList from './fragments/edit-description-list.jsx'
38
37
  import { DOILink } from './fragments/doi-link'
39
38
 
40
39
  import { TabRoutesDraft } from './routes/tab-routes-draft'
40
+ import { FollowToggles } from './common/follow-toggles'
41
41
 
42
42
  export interface DraftContainerProps {
43
43
  dataset
@@ -107,14 +107,30 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
107
107
  pageHeading={description.Name}
108
108
  modality={modality}
109
109
  renderEditor={() => (
110
- <EditDescriptionField
111
- datasetId={datasetId}
112
- field="Name"
113
- rows={2}
114
- description={description.Name}
115
- editMode={hasEdit}>
116
- {description.Name}
117
- </EditDescriptionField>
110
+ <>
111
+ <EditDescriptionField
112
+ datasetId={datasetId}
113
+ field="Name"
114
+ rows={2}
115
+ description={description.Name}
116
+ editMode={hasEdit}>
117
+ {description.Name}
118
+ </EditDescriptionField>
119
+ <FollowToggles>
120
+ <FollowDataset
121
+ profile={profile}
122
+ datasetId={dataset.id}
123
+ following={dataset.following}
124
+ followers={dataset.followers.length}
125
+ />
126
+ <StarDataset
127
+ profile={profile}
128
+ datasetId={dataset.id}
129
+ starred={dataset.starred}
130
+ stars={dataset.stars.length}
131
+ />
132
+ </FollowToggles>
133
+ </>
118
134
  )}
119
135
  />
120
136
  <DatasetAlertDraft
@@ -123,34 +139,7 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
123
139
  hasDraftChanges={hasDraftChanges}
124
140
  hasSnapshot={dataset.snapshots.length !== 0}
125
141
  />
126
- <div className="container">
127
- <div className="grid grid-between dataset-header-meta">
128
- <div className="col col-8 col-lg">
129
- {summary && (
130
- <DatasetHeaderMeta
131
- size={dataset.draft.size}
132
- totalFiles={summary.totalFiles}
133
- datasetId={datasetId}
134
- />
135
- )}
136
- </div>
137
- <div className="col follow-bookmark">
138
- <FollowDataset
139
- profile={profile}
140
- datasetId={dataset.id}
141
- following={dataset.following}
142
- followers={dataset.followers.length}
143
- />
144
- <StarDataset
145
- profile={profile}
146
- datasetId={dataset.id}
147
- starred={dataset.starred}
148
- stars={dataset.stars.length}
149
- />
150
- </div>
151
- </div>
152
- </div>
153
- <div className="container">
142
+ <div className="dataset-content container">
154
143
  <div className="grid grid-between">
155
144
  <div className="col col-lg col-8">
156
145
  <div className="dataset-validation">
@@ -191,7 +180,10 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
191
180
  </DatasetPageTabContainer>
192
181
  </div>
193
182
  <div className="col sidebar">
194
- {' '}
183
+ <MetaDataBlock
184
+ heading="OpenNeuro Accession Number"
185
+ item={datasetId}
186
+ />
195
187
  <EditDescriptionList
196
188
  className="dmb-inline-list"
197
189
  datasetId={datasetId}
@@ -19,7 +19,7 @@ const FileViewerType = ({ path, url, data }) => {
19
19
  path.endsWith('.txt')
20
20
  ) {
21
21
  return <FileViewerText data={data} />
22
- } else if (path.endsWith('.nii.gz') || path.endsWith('.nii')) {
22
+ } else if (path.endsWith('.nii.gz') || path.endsWith('.nii') || path.endsWith('.mgh') || path.endsWith('.mgz')) {
23
23
  return <FileViewerNifti imageUrl={url} />
24
24
  } else if (path.endsWith('.json')) {
25
25
  return <FileViewerJson data={data} />
@@ -8,6 +8,18 @@ import { WarnButton } from '@openneuro/components/warn-button'
8
8
  import { AccordionWrap } from '@openneuro/components/accordion'
9
9
  import styled from '@emotion/styled'
10
10
  import { Tooltip } from '@openneuro/components/tooltip'
11
+ import bytes from 'bytes'
12
+
13
+ const FileTreeMeta = styled.span`
14
+ position: absolute;
15
+ top: 8px;
16
+ right: 8px;
17
+ `
18
+
19
+ const FileTreeMetaLabel = styled.label`
20
+ font-weight: bold;
21
+ padding-left: 1ch;
22
+ `
11
23
 
12
24
  const StyleWrapper = styled.div`
13
25
  .filetree-wrapper {
@@ -28,6 +40,7 @@ const Files = ({
28
40
  files,
29
41
  editMode = false,
30
42
  datasetPermissions,
43
+ summary,
31
44
  }) => {
32
45
  const [filesToDelete, setFilesToDelete] = useState({})
33
46
  const [isDeleting, setIsDeleting] = useState(false)
@@ -108,6 +121,14 @@ const Files = ({
108
121
  </Media>
109
122
  <Media greaterThanOrEqual="medium">
110
123
  <div className="filetree-item">
124
+ {summary && (
125
+ <FileTreeMeta>
126
+ <FileTreeMetaLabel>Files:</FileTreeMetaLabel>{' '}
127
+ {summary.totalFiles}{' '}
128
+ <FileTreeMetaLabel>Size:</FileTreeMetaLabel>{' '}
129
+ {bytes(summary.size)}
130
+ </FileTreeMeta>
131
+ )}
111
132
  <FileTree
112
133
  datasetId={datasetId}
113
134
  snapshotTag={snapshotTag}
@@ -136,6 +157,7 @@ Files.propTypes = {
136
157
  editMode: PropTypes.bool,
137
158
  fetchMore: PropTypes.func,
138
159
  datasetPermissions: PropTypes.object,
160
+ summary: PropTypes.object,
139
161
  }
140
162
 
141
163
  export default Files
@@ -11,20 +11,6 @@ import EditDescriptionField from '../fragments/edit-description-field'
11
11
  */
12
12
  export const DatasetDefault = ({ dataset, hasEdit }) => (
13
13
  <>
14
- <ReadMore
15
- fileTree={true}
16
- id="collapse-tree"
17
- expandLabel="Expand File Tree"
18
- collapseLabel="Collapse File Tree">
19
- <Files
20
- datasetId={dataset.id}
21
- snapshotTag={null}
22
- datasetName={dataset.draft.description.Name}
23
- files={dataset.draft.files}
24
- editMode={hasEdit}
25
- datasetPermissions={dataset.permissions}
26
- />
27
- </ReadMore>
28
14
  <MetaDataBlock
29
15
  heading="README"
30
16
  className="dataset-readme markdown-body"
@@ -45,6 +31,15 @@ export const DatasetDefault = ({ dataset, hasEdit }) => (
45
31
  </EditDescriptionField>
46
32
  )}
47
33
  />
34
+ <Files
35
+ datasetId={dataset.id}
36
+ snapshotTag={null}
37
+ datasetName={dataset.draft.description.Name}
38
+ files={dataset.draft.files}
39
+ editMode={hasEdit}
40
+ datasetPermissions={dataset.permissions}
41
+ summary={dataset.draft?.summary}
42
+ />
48
43
  <Comments
49
44
  datasetId={dataset.id}
50
45
  uploader={dataset.uploader}
@@ -10,20 +10,6 @@ import Comments from '../comments/comments'
10
10
  */
11
11
  export const SnapshotDefault = ({ dataset, snapshot }) => (
12
12
  <>
13
- <ReadMore
14
- fileTree={true}
15
- id="collapse-tree"
16
- expandLabel="Read More"
17
- collapseLabel="Collapse">
18
- <Files
19
- datasetId={dataset.id}
20
- snapshotTag={snapshot.tag}
21
- datasetName={snapshot.description.Name}
22
- files={snapshot.files}
23
- editMode={false}
24
- datasetPermissions={dataset.permissions}
25
- />
26
- </ReadMore>
27
13
  <MetaDataBlock
28
14
  heading="README"
29
15
  item={
@@ -35,6 +21,15 @@ export const SnapshotDefault = ({ dataset, snapshot }) => (
35
21
  }
36
22
  className="dataset-readme markdown-body"
37
23
  />
24
+ <Files
25
+ datasetId={dataset.id}
26
+ snapshotTag={snapshot.tag}
27
+ datasetName={snapshot.description.Name}
28
+ files={snapshot.files}
29
+ editMode={false}
30
+ datasetPermissions={dataset.permissions}
31
+ summary={snapshot?.summary}
32
+ />
38
33
  <Comments
39
34
  datasetId={dataset.id}
40
35
  uploader={dataset.uploader}
@@ -20,7 +20,6 @@ import {
20
20
  ValidationBlock,
21
21
  CloneDropdown,
22
22
  DatasetHeader,
23
- DatasetHeaderMeta,
24
23
  DatasetGitAccess,
25
24
  VersionList,
26
25
  DatasetTools,
@@ -40,6 +39,8 @@ import { StarDataset } from './mutations/star'
40
39
  import { SNAPSHOT_FIELDS } from '../datalad/dataset/dataset-query-fragments.js'
41
40
  import { DOILink } from './fragments/doi-link'
42
41
  import { TabRoutesSnapshot } from './routes/tab-routes-snapshot'
42
+ import schemaGenerator from '../utils/json-ld.js'
43
+ import { FollowToggles } from './common/follow-toggles'
43
44
 
44
45
  const formatDate = dateObject =>
45
46
  new Date(dateObject).toISOString().split('T')[0]
@@ -56,7 +57,7 @@ type SnapshotContainerProps = {
56
57
  snapshot
57
58
  }
58
59
 
59
- const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
60
+ export const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
60
61
  dataset,
61
62
  tag,
62
63
  snapshot,
@@ -94,14 +95,31 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
94
95
  <title>
95
96
  {description.Name} - {pageTitle}
96
97
  </title>
98
+ <script type="application/ld+json">{schemaGenerator(snapshot)}</script>
97
99
  </Helmet>
98
100
  <div
99
101
  className={`dataset dataset-draft dataset-page dataset-page-${modality?.toLowerCase()}`}>
100
102
  {summary && (
101
- <DatasetHeader
102
- pageHeading={description.Name}
103
- modality={summary?.modalities[0]}
104
- />
103
+ <>
104
+ <DatasetHeader
105
+ pageHeading={description.Name}
106
+ modality={summary?.modalities[0]}>
107
+ <FollowToggles>
108
+ <FollowDataset
109
+ profile={profile}
110
+ datasetId={dataset.id}
111
+ following={dataset.following}
112
+ followers={dataset.followers.length}
113
+ />
114
+ <StarDataset
115
+ profile={profile}
116
+ datasetId={dataset.id}
117
+ starred={dataset.starred}
118
+ stars={dataset.stars.length}
119
+ />
120
+ </FollowToggles>
121
+ </DatasetHeader>
122
+ </>
105
123
  )}
106
124
  {snapshot?.deprecated && (
107
125
  <DatasetAlertVersion
@@ -111,34 +129,7 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
111
129
  hasEdit={hasEdit}
112
130
  />
113
131
  )}
114
- <div className="container">
115
- <div className="grid grid-between dataset-header-meta">
116
- <div className="col col-8 col-lg">
117
- {summary && (
118
- <DatasetHeaderMeta
119
- size={snapshot.size}
120
- totalFiles={summary.totalFiles}
121
- datasetId={datasetId}
122
- />
123
- )}
124
- </div>
125
- <div className="col follow-bookmark">
126
- <FollowDataset
127
- profile={profile}
128
- datasetId={dataset.id}
129
- following={dataset.following}
130
- followers={dataset.followers.length}
131
- />
132
- <StarDataset
133
- profile={profile}
134
- datasetId={dataset.id}
135
- starred={dataset.starred}
136
- stars={dataset.stars.length}
137
- />
138
- </div>
139
- </div>
140
- </div>
141
- <div className="container">
132
+ <div className="dataset-content container">
142
133
  <div className="grid grid-between">
143
134
  <div className="col col-lg col-8">
144
135
  <div className="dataset-validation">
@@ -179,6 +170,10 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
179
170
  </DatasetPageTabContainer>
180
171
  </div>
181
172
  <div className="col sidebar">
173
+ <MetaDataBlock
174
+ heading="OpenNeuro Accession Number"
175
+ item={datasetId}
176
+ />
182
177
  <MetaDataBlock
183
178
  heading="Authors"
184
179
  item={
@@ -0,0 +1,300 @@
1
+ // Example queries responses for use in tests
2
+ export const dataset = {
3
+ id: 'ds001032',
4
+ created: '2021-12-17T22:24:05.500Z',
5
+ public: true,
6
+ following: true,
7
+ followers: [
8
+ {
9
+ userId: '18492691-707f-4161-bc73-6ed22ce40138',
10
+ __typename: 'Follower',
11
+ },
12
+ ],
13
+ starred: false,
14
+ stars: [],
15
+ worker: 'datalad-0',
16
+ draft: {
17
+ id: 'ds001032',
18
+ modified: '2021-12-17T22:32:35.282Z',
19
+ readme:
20
+ 'This dataset was obtained from the OpenfMRI project (http://www.openfmri.org).\nAccession #: ds003\nDescription: Rhyme judgment\n\nRelease history:\n10/06/2011: initial release\n3/21/2013: Updated release with QA information\n\nThis dataset is made available under the Public Domain Dedication and License \nv1.0, whose full text can be found at \nhttp://www.opendatacommons.org/licenses/pddl/1.0/. \nWe hope that all users will follow the ODC Attribution/Share-Alike \nCommunity Norms (http://www.opendatacommons.org/norms/odc-by-sa/); \nin particular, while not legally required, we hope that all users \nof the data will acknowledge the OpenfMRI project and NSF Grant \nOCI-1131441 (R. Poldrack, PI) in any publications.\n',
21
+ head: 'd62fdc42e2a568a6f89e33d68d3ef343ff883e02',
22
+ size: 623389,
23
+ description: {
24
+ Name: 'DS003-downsampled (only T1)',
25
+ Authors: ['J. Doe', 'J. Doe', 'J. Doe'],
26
+ DatasetDOI: null,
27
+ License: 'CC0',
28
+ Acknowledgements: null,
29
+ HowToAcknowledge: null,
30
+ Funding: null,
31
+ ReferencesAndLinks: null,
32
+ EthicsApprovals: null,
33
+ __typename: 'Description',
34
+ },
35
+ summary: {
36
+ modalities: ['MRI'],
37
+ secondaryModalities: ['MRI_Structural'],
38
+ sessions: [],
39
+ subjects: ['01', '02'],
40
+ subjectMetadata: [
41
+ {
42
+ participantId: '01',
43
+ age: 25,
44
+ sex: 'M',
45
+ group: null,
46
+ __typename: 'SubjectMetadata',
47
+ },
48
+ ],
49
+ tasks: [],
50
+ size: 623389,
51
+ totalFiles: 7,
52
+ dataProcessed: false,
53
+ pet: null,
54
+ __typename: 'Summary',
55
+ },
56
+ __typename: 'Draft',
57
+ issues: [
58
+ {
59
+ severity: 'warning',
60
+ code: 82,
61
+ reason:
62
+ 'Tabular file contains custom columns not described in a data dictionary',
63
+ files: [
64
+ {
65
+ evidence:
66
+ 'Columns: sex, age not defined, please define in: /participants.json',
67
+ line: null,
68
+ character: null,
69
+ reason:
70
+ 'Tabular file contains custom columns not described in a data dictionary',
71
+ file: {
72
+ name: 'participants.tsv',
73
+ path: '/datalad/ds001032/participants.tsv',
74
+ relativePath: '/participants.tsv',
75
+ __typename: 'ValidationIssueFileDetail',
76
+ },
77
+ __typename: 'ValidationIssueFile',
78
+ },
79
+ ],
80
+ additionalFileCount: 0,
81
+ __typename: 'ValidationIssue',
82
+ },
83
+ ],
84
+ },
85
+ __typename: 'Dataset',
86
+ permissions: {
87
+ id: 'ds001032',
88
+ userPermissions: [
89
+ {
90
+ user: {
91
+ id: '18492691-707f-4161-bc73-6ed22ce40138',
92
+ email: 'test@example.com',
93
+ __typename: 'User',
94
+ },
95
+ level: 'admin',
96
+ __typename: 'Permission',
97
+ },
98
+ ],
99
+ __typename: 'DatasetPermissions',
100
+ },
101
+ snapshots: [
102
+ {
103
+ id: 'ds001032:1.0.0',
104
+ tag: '1.0.0',
105
+ created: '2021-12-17T22:22:49.000Z',
106
+ hexsha: 'e4daf5567b86426b13e2d319859164e410975056',
107
+ __typename: 'Snapshot',
108
+ },
109
+ {
110
+ id: 'ds001032:2.0.0',
111
+ tag: '2.0.0',
112
+ created: '2021-12-17T22:32:08.000Z',
113
+ hexsha: 'd62fdc42e2a568a6f89e33d68d3ef343ff883e02',
114
+ __typename: 'Snapshot',
115
+ },
116
+ ],
117
+ metadata: {
118
+ datasetId: 'ds001032',
119
+ datasetUrl: null,
120
+ datasetName: null,
121
+ firstSnapshotCreatedAt: null,
122
+ latestSnapshotCreatedAt: null,
123
+ dxStatus: '',
124
+ tasksCompleted: [],
125
+ trialCount: null,
126
+ grantFunderName: '',
127
+ grantIdentifier: '',
128
+ studyDesign: '',
129
+ studyDomain: '',
130
+ studyLongitudinal: '',
131
+ dataProcessed: null,
132
+ species: '',
133
+ associatedPaperDOI: '',
134
+ openneuroPaperDOI: '',
135
+ seniorAuthor: null,
136
+ adminUsers: [],
137
+ ages: [],
138
+ modalities: [],
139
+ affirmedDefaced: true,
140
+ affirmedConsent: false,
141
+ __typename: 'Metadata',
142
+ },
143
+ comments: [],
144
+ uploader: {
145
+ id: '18492691-707f-4161-bc73-6ed22ce40138',
146
+ name: 'Test User',
147
+ email: 'test@example.com',
148
+ __typename: 'User',
149
+ },
150
+ analytics: {
151
+ downloads: 0,
152
+ views: 23,
153
+ __typename: 'Analytic',
154
+ },
155
+ derivatives: [],
156
+ onBrainlife: false,
157
+ }
158
+
159
+ export const snapshot = {
160
+ id: 'ds001032:1.0.0',
161
+ tag: '1.0.0',
162
+ created: '2021-12-17T22:32:08.000Z',
163
+ readme:
164
+ 'This dataset was obtained from the OpenfMRI project (http://www.openfmri.org).\nAccession #: ds003\nDescription: Rhyme judgment\n\nRelease history:\n10/06/2011: initial release\n3/21/2013: Updated release with QA information\n\nThis dataset is made available under the Public Domain Dedication and License \nv1.0, whose full text can be found at \nhttp://www.opendatacommons.org/licenses/pddl/1.0/. \nWe hope that all users will follow the ODC Attribution/Share-Alike \nCommunity Norms (http://www.opendatacommons.org/norms/odc-by-sa/); \nin particular, while not legally required, we hope that all users \nof the data will acknowledge the OpenfMRI project and NSF Grant \nOCI-1131441 (R. Poldrack, PI) in any publications.\n',
165
+ size: 623389,
166
+ deprecated: null,
167
+ description: {
168
+ Name: 'DS003-downsampled (only T1)',
169
+ Authors: ['J. Doe', 'J. Doe', 'J. Doe'],
170
+ DatasetDOI: null,
171
+ License: 'CC0',
172
+ Acknowledgements: null,
173
+ HowToAcknowledge: null,
174
+ Funding: null,
175
+ ReferencesAndLinks: null,
176
+ EthicsApprovals: null,
177
+ __typename: 'Description',
178
+ },
179
+ files: [
180
+ {
181
+ id: '7dcbfd4d8ef17174c6eb2cc023f7950c682563a5',
182
+ key: '4feabfe8803db741e9a0c5ad00bc3ada109558e3',
183
+ filename: 'CHANGES',
184
+ size: 52,
185
+ directory: null,
186
+ annexed: false,
187
+ __typename: 'DatasetFile',
188
+ },
189
+ {
190
+ id: '63888a199a5ce37377b1cd708cda59577dad218f',
191
+ key: 'fa84e5f958ec72d42b3e196e592f6db9f7104b19',
192
+ filename: 'README',
193
+ size: 709,
194
+ directory: null,
195
+ annexed: false,
196
+ __typename: 'DatasetFile',
197
+ },
198
+ {
199
+ id: '0a2a5d8d72a31f03608db59c4cfd650aba77c363',
200
+ key: 'b08aa0ec5b5e716479824859524a22140fb2af82',
201
+ filename: 'T1w.json',
202
+ size: 196,
203
+ directory: null,
204
+ annexed: false,
205
+ __typename: 'DatasetFile',
206
+ },
207
+ {
208
+ id: 'a2922b427c5c997e77ce058e0ce57ffd17123a7f',
209
+ key: '0b1856b91c11f67098ce60114417a62dd55730a5',
210
+ filename: 'dataset_description.json',
211
+ size: 172,
212
+ directory: null,
213
+ annexed: false,
214
+ __typename: 'DatasetFile',
215
+ },
216
+ {
217
+ id: 'f682a32c9538082fa6c8ad11e9a536dc07d1d0cf',
218
+ key: '37ecbdc7ab8ffaf2cddecc338092f6679089287d',
219
+ filename: 'participants.tsv',
220
+ size: 36,
221
+ directory: null,
222
+ annexed: false,
223
+ __typename: 'DatasetFile',
224
+ },
225
+ {
226
+ id: 'directory:sub-01',
227
+ key: null,
228
+ filename: 'sub-01',
229
+ size: 1,
230
+ directory: true,
231
+ annexed: null,
232
+ __typename: 'DatasetFile',
233
+ },
234
+ {
235
+ id: 'directory:sub-02',
236
+ key: null,
237
+ filename: 'sub-02',
238
+ size: 1,
239
+ directory: true,
240
+ annexed: null,
241
+ __typename: 'DatasetFile',
242
+ },
243
+ ],
244
+ summary: {
245
+ modalities: ['MRI'],
246
+ secondaryModalities: ['MRI_Structural'],
247
+ sessions: [],
248
+ subjects: ['01', '02'],
249
+ subjectMetadata: [
250
+ {
251
+ participantId: '01',
252
+ age: 25,
253
+ sex: 'M',
254
+ group: null,
255
+ __typename: 'SubjectMetadata',
256
+ },
257
+ ],
258
+ tasks: [],
259
+ size: 623389,
260
+ totalFiles: 7,
261
+ dataProcessed: false,
262
+ pet: null,
263
+ __typename: 'Summary',
264
+ },
265
+ analytics: {
266
+ downloads: 0,
267
+ views: 24,
268
+ __typename: 'Analytic',
269
+ },
270
+ issues: [
271
+ {
272
+ severity: 'warning',
273
+ code: 82,
274
+ reason:
275
+ 'Tabular file contains custom columns not described in a data dictionary',
276
+ files: [
277
+ {
278
+ evidence:
279
+ 'Columns: sex, age not defined, please define in: /participants.json',
280
+ line: null,
281
+ character: null,
282
+ reason:
283
+ 'Tabular file contains custom columns not described in a data dictionary',
284
+ file: {
285
+ name: 'participants.tsv',
286
+ path: '/datalad/ds001032/participants.tsv',
287
+ relativePath: '/participants.tsv',
288
+ __typename: 'ValidationIssueFileDetail',
289
+ },
290
+ __typename: 'ValidationIssueFile',
291
+ },
292
+ ],
293
+ additionalFileCount: 0,
294
+ __typename: 'ValidationIssue',
295
+ },
296
+ ],
297
+ __typename: 'Snapshot',
298
+ hexsha: 'd62fdc42e2a568a6f89e33d68d3ef343ff883e02',
299
+ onBrainlife: false,
300
+ }