@openneuro/app 4.23.0 → 4.24.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openneuro/app",
3
- "version": "4.23.0",
3
+ "version": "4.24.0-alpha.0",
4
4
  "description": "React JS web frontend for the OpenNeuro platform.",
5
5
  "license": "MIT",
6
6
  "main": "public/client.js",
@@ -16,14 +16,14 @@
16
16
  "dependencies": {
17
17
  "@apollo/client": "3.7.2",
18
18
  "@artsy/fresnel": "^1.3.1",
19
- "@elastic/apm-rum": "5.11.0",
19
+ "@elastic/apm-rum": "5.16.0",
20
20
  "@emotion/react": "11.11.1",
21
21
  "@emotion/styled": "11.11.0",
22
22
  "@niivue/niivue": "0.34.0",
23
- "@openneuro/client": "^4.23.0",
24
- "@openneuro/components": "^4.23.0",
23
+ "@openneuro/client": "^4.24.0-alpha.0",
24
+ "@openneuro/components": "^4.24.0-alpha.0",
25
25
  "@tanstack/react-table": "^8.9.3",
26
- "bids-validator": "1.13.0",
26
+ "bids-validator": "1.14.6",
27
27
  "bytes": "^3.0.0",
28
28
  "comlink": "^4.0.5",
29
29
  "date-fns": "^2.16.1",
@@ -54,7 +54,7 @@
54
54
  "@testing-library/react": "^14.2.1",
55
55
  "@types/dompurify": "^3",
56
56
  "@types/jsdom": "^16",
57
- "@types/node": "18.11.9",
57
+ "@types/node": "20.12.7",
58
58
  "@types/react": "^17.0.8",
59
59
  "@types/react-dom": "^18.2.19",
60
60
  "@types/react-router-dom": "5.3.3",
@@ -62,17 +62,17 @@
62
62
  "core-js": "3.25.1",
63
63
  "esbuild-plugin-globals": "^0.1.1",
64
64
  "history": "5.3.0",
65
- "jsdom": "^16.5.3",
65
+ "jsdom": "24.0.0",
66
66
  "object.fromentries": "^2.0.0",
67
67
  "rollup-plugin-polyfill-node": "0.12.0",
68
68
  "sass": "^1.32.8",
69
69
  "stream-browserify": "^3.0.0",
70
70
  "typescript": "5.1.6",
71
- "vite": "4.5.2",
72
- "vitest": "0.34.4"
71
+ "vite": "4.5.3",
72
+ "vitest": "1.5.0"
73
73
  },
74
74
  "publishConfig": {
75
75
  "access": "public"
76
76
  },
77
- "gitHead": "e86df78635d7ac6cfa03a2add5760b8539103583"
77
+ "gitHead": "4e271231c20d21e4c8b5ba8851d67cb94b7f739a"
78
78
  }
@@ -13,7 +13,7 @@ exports[`SnapshotContainer component > includes JSON-LD data in the header 1`] =
13
13
  "onChangeClientState": [Function],
14
14
  "scriptTags": [
15
15
  {
16
- "innerHTML": "{\\"@context\\":\\"http://schema.org\\",\\"@type\\":\\"Dataset\\",\\"name\\":\\"DS003-downsampled (only T1)\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"J. Doe\\",\\"givenName\\":\\"J.\\",\\"familyName\\":\\"Doe\\"},{\\"@type\\":\\"Person\\",\\"name\\":\\"J. Doe\\",\\"givenName\\":\\"J.\\",\\"familyName\\":\\"Doe\\"},{\\"@type\\":\\"Person\\",\\"name\\":\\"J. Doe\\",\\"givenName\\":\\"J.\\",\\"familyName\\":\\"Doe\\"}],\\"datePublished\\":\\"2021-12-17T22:32:08.000Z\\",\\"dateModified\\":\\"2021-12-17T22:32:08.000Z\\",\\"license\\":\\"https://creativecommons.org/publicdomain/zero/1.0/\\",\\"publisher\\":{\\"@type\\":\\"Organization\\",\\"name\\":\\"OpenNeuro\\"},\\"description\\":\\"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\\",\\"version\\":\\"1.0.0\\",\\"url\\":\\"https://openneuro.org/datasets/ds001032/versions/1.0.0\\"}",
16
+ "innerHTML": "{"@context":"http://schema.org","@type":"Dataset","name":"DS003-downsampled (only T1)","author":[{"@type":"Person","name":"J. Doe","givenName":"J.","familyName":"Doe"},{"@type":"Person","name":"J. Doe","givenName":"J.","familyName":"Doe"},{"@type":"Person","name":"J. Doe","givenName":"J.","familyName":"Doe"}],"datePublished":"2021-12-17T22:32:08.000Z","dateModified":"2021-12-17T22:32:08.000Z","license":"https://creativecommons.org/publicdomain/zero/1.0/","publisher":{"@type":"Organization","name":"OpenNeuro"},"description":"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","version":"1.0.0","url":"https://openneuro.org/datasets/ds001032/versions/1.0.0"}",
17
17
  "type": "application/ld+json",
18
18
  },
19
19
  ],
@@ -16,7 +16,11 @@ export const NemarButton: React.FC<NemarButtonProps> = ({
16
16
  <>
17
17
  {onNemar && (
18
18
  <div className="brainlife-block">
19
- <Tooltip tooltip="View and analyze on NEMAR" flow="up">
19
+ <Tooltip
20
+ tooltip="View and analyze this dataset on the NEMAR OpenNeuro portal for MEG, iEEG, and EEG data"
21
+ flow="up"
22
+ wrapText={true}
23
+ >
20
24
  <Button
21
25
  className="brainlife-link"
22
26
  primary={true}
@@ -14,14 +14,23 @@ const FileViewerNifti = ({
14
14
  url: imageUrl,
15
15
  colorMap: "gray",
16
16
  opacity: 1,
17
- visible: true,
18
17
  limitFrames4D: 5,
19
18
  },
20
19
  ]
21
20
  const nv = new Niivue({ dragAndDropEnabled: false })
22
21
  ;(window as any).niivue = nv
23
22
  nv.attachToCanvas(canvas.current)
24
- nv.loadVolumes(volumeList) // press the "v" key to cycle through volumes
23
+ nv.loadVolumes(volumeList) // press the "v" key to cycle through views (axial, coronal, sagittal, 3D, etc.)
24
+ nv.graph.autoSizeMultiplanar = true // use autosizing
25
+ nv.opts.multiplanarForceRender = true // ensure that we draw the time series graph in the tile usually reserved for the 3D render
26
+ nv.graph.normalizeValues = false // use raw data values on y-axis
27
+ nv.graph.opacity = 1.0 // show the graph
28
+ // Notes:
29
+ // 1. If an image only has one volume, the timeseries graph will not be visible.
30
+ // The 3D render will be placed in the graph tile instead.
31
+ // 2. Users can navigate volumes forward and backward in the series using the left and right arrow keys on desktop devices
32
+ // 3. On touch screens, users can tap on the timeseries graph to jump to a volume index
33
+ // 4. Users can load all volumes by clicking on the "..." displayed on the timeseries graph
25
34
  }, [imageUrl])
26
35
 
27
36
  return <canvas ref={canvas} height={800} />
@@ -7,22 +7,22 @@ import OrcidGeneral from "./orcid/general.jsx"
7
7
  import OrcidEmail from "./orcid/email.jsx"
8
8
  import OrcidGiven from "./orcid/given.jsx"
9
9
  import OrcidFamily from "./orcid/family.jsx"
10
+ import FourOFourPage from "./404page"
10
11
 
11
- class ErrorRoute extends React.Component {
12
- render() {
13
- return (
14
- <div className="container errors">
15
- <div className="panel">
16
- <Routes>
17
- <Route path="orcid" element={<OrcidGeneral />} />
18
- <Route path="orcid/email" element={<OrcidEmail />} />
19
- <Route path="orcid/given" element={<OrcidGiven />} />
20
- <Route path="orcid/family" element={<OrcidFamily />} />
21
- </Routes>
22
- </div>
12
+ function ErrorRoute() {
13
+ return (
14
+ <div className="container errors">
15
+ <div className="panel">
16
+ <Routes>
17
+ <Route path="orcid" element={<OrcidGeneral />} />
18
+ <Route path="orcid/email" element={<OrcidEmail />} />
19
+ <Route path="orcid/given" element={<OrcidGiven />} />
20
+ <Route path="orcid/family" element={<OrcidFamily />} />
21
+ <Route path="*" element={<FourOFourPage />} />
22
+ </Routes>
23
23
  </div>
24
- )
25
- }
24
+ </div>
25
+ )
26
26
  }
27
27
 
28
28
  export default ErrorRoute
@@ -39,7 +39,7 @@ const AppRoutes: React.VoidFunctionComponent = () => (
39
39
  path="/dashboard"
40
40
  element={<Navigate to="/search?mydatasets" replace />}
41
41
  />
42
- <Route element={<FourOFourPage />} />
42
+ <Route path="/*" element={<FourOFourPage />} />
43
43
  </Routes>
44
44
  )
45
45
 
@@ -155,46 +155,11 @@ export interface SearchParams {
155
155
  tracerRadionuclides: string[]
156
156
  sortBy_available
157
157
  sortBy_selected
158
+ bidsDatasetType_available: string[]
159
+ bidsDatasetType_selected: string | null
158
160
  }
159
161
 
160
- // TODO: move to this initial state
161
- // and load dynamic options on mount
162
162
  const initialSearchParams: SearchParams = {
163
- keywords: [],
164
- searchAllDatasets: false,
165
- datasetType_available,
166
- datasetType_selected: null,
167
- datasetStatus_available,
168
- datasetStatus_selected: null,
169
- modality_available,
170
- modality_selected: null,
171
- ageRange: [null, null],
172
- subjectCountRange: [null, null],
173
- diagnosis_available: [],
174
- diagnosis_selected: null,
175
- tasks: [],
176
- authors: [],
177
- // more
178
- sex_available: [],
179
- sex_selected: null,
180
- date_available: [],
181
- date_selected: null,
182
- species_available: [],
183
- species_selected: null,
184
- section_available: [],
185
- section_selected: null,
186
- studyDomains: [],
187
- bodyParts: [],
188
- scannerManufacturers: [],
189
- scannerManufacturersModelNames: [],
190
- tracerNames: [],
191
- tracerRadionuclides: [],
192
- sortBy_available: sortBy,
193
- sortBy_selected: sortBy[0],
194
- }
195
-
196
- // TODO: (stretch) delete and move to dynamically loaded initialSearchParams
197
- const TEMPORARY_initialSearchParams: SearchParams = {
198
163
  keywords: [],
199
164
  searchAllDatasets: false,
200
165
  datasetType_available,
@@ -237,6 +202,8 @@ const TEMPORARY_initialSearchParams: SearchParams = {
237
202
  tracerRadionuclides: [],
238
203
  sortBy_available: sortBy,
239
204
  sortBy_selected: sortBy[0],
205
+ bidsDatasetType_available: ["raw", "derivative"],
206
+ bidsDatasetType_selected: null,
240
207
  }
241
208
 
242
- export default TEMPORARY_initialSearchParams
209
+ export default initialSearchParams
@@ -0,0 +1,33 @@
1
+ import React, { FC, useContext } from "react"
2
+ import { SearchParamsCtx } from "../search-params-ctx"
3
+ import { FacetSelect } from "@openneuro/components/facets"
4
+ import { AccordionTab, AccordionWrap } from "@openneuro/components/accordion"
5
+
6
+ const DatasetTypeSelect: FC = () => {
7
+ const { searchParams, setSearchParams } = useContext(SearchParamsCtx)
8
+
9
+ const { bidsDatasetType_selected, bidsDatasetType_available } = searchParams
10
+ const setDatasetType = (bidsDatasetType_selected) =>
11
+ setSearchParams((prevState) => ({
12
+ ...prevState,
13
+ bidsDatasetType_selected,
14
+ }))
15
+
16
+ return (
17
+ <AccordionWrap className="facet-accordion">
18
+ <AccordionTab
19
+ accordionStyle="plain"
20
+ label="Dataset Type"
21
+ startOpen={false}
22
+ >
23
+ <FacetSelect
24
+ selected={bidsDatasetType_selected}
25
+ setSelected={setDatasetType}
26
+ items={bidsDatasetType_available}
27
+ />
28
+ </AccordionTab>
29
+ </AccordionWrap>
30
+ )
31
+ }
32
+
33
+ export default DatasetTypeSelect
@@ -4,6 +4,7 @@ import ModalitySelect from "./modality-select"
4
4
  import ShowDatasetRadios from "./show-datasets-radios"
5
5
  import AgeRangeInput from "./age-range-input"
6
6
  import SubjectCountRangeInput from "./subject-count-range-input"
7
+ import DatasetTypeSelect from "./dataset-type-select"
7
8
  import DiagnosisSelect from "./diagnosis-select"
8
9
  import TaskInput from "./task-input"
9
10
  import AuthorInput from "./author-input"
@@ -24,6 +25,7 @@ export {
24
25
  AllDatasetsToggle,
25
26
  AuthorInput,
26
27
  BodyPartsInput,
28
+ DatasetTypeSelect,
27
29
  DateRadios,
28
30
  DiagnosisSelect,
29
31
  KeywordInput,
@@ -16,6 +16,7 @@ import {
16
16
  AllDatasetsToggle,
17
17
  AuthorInput,
18
18
  BodyPartsInput,
19
+ DatasetTypeSelect,
19
20
  DateRadios,
20
21
  DiagnosisSelect,
21
22
  KeywordInput,
@@ -101,14 +102,12 @@ const SearchContainer: FC<SearchContainerProps> = ({ portalContent }) => {
101
102
 
102
103
  const { searchParams, setSearchParams } = useContext(SearchParamsCtx)
103
104
  const modality = portalContent?.modality || null
104
- useEffect(() => {
105
- setDefaultSearch(
106
- modality,
107
- searchParams,
108
- setSearchParams,
109
- new URLSearchParams(location.search),
110
- )
111
- }, [modality, searchParams.modality_selected, setSearchParams, location])
105
+ setDefaultSearch(
106
+ modality,
107
+ searchParams,
108
+ setSearchParams,
109
+ new URLSearchParams(location.search),
110
+ )
112
111
 
113
112
  const { loading, data, fetchMore, refetch, variables, error } =
114
113
  useSearchResults()
@@ -166,6 +165,7 @@ const SearchContainer: FC<SearchContainerProps> = ({ portalContent }) => {
166
165
  {!portalContent
167
166
  ? <ModalitySelect portalStyles={true} label="Modalities" />
168
167
  : <ModalitySelect portalStyles={false} label="Choose Modality" />}
168
+ <DatasetTypeSelect />
169
169
  <AgeRangeInput />
170
170
  <SubjectCountRangeInput />
171
171
  <DiagnosisSelect />
@@ -123,6 +123,7 @@ export const getSelectParams = ({
123
123
  scannerManufacturersModelNames,
124
124
  tracerNames,
125
125
  tracerRadionuclides,
126
+ bidsDatasetType_selected,
126
127
  }) => ({
127
128
  keywords,
128
129
  modality_selected,
@@ -144,6 +145,7 @@ export const getSelectParams = ({
144
145
  scannerManufacturersModelNames,
145
146
  tracerNames,
146
147
  tracerRadionuclides,
148
+ bidsDatasetType_selected,
147
149
  })
148
150
 
149
151
  /**