@openneuro/app 4.30.2 → 4.31.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 (58) hide show
  1. package/package.json +5 -5
  2. package/src/assets/activity-icon.png +0 -0
  3. package/src/assets/icon-archived.png +0 -0
  4. package/src/assets/icon-saved.png +0 -0
  5. package/src/assets/icon-unread.png +0 -0
  6. package/src/client.jsx +1 -1
  7. package/src/scripts/datalad/dataset/dataset-query-fragments.js +4 -14
  8. package/src/scripts/dataset/__tests__/__snapshots__/snapshot-container.spec.tsx.snap +4 -304
  9. package/src/scripts/dataset/components/ValidationBlock.tsx +13 -15
  10. package/src/scripts/dataset/components/__tests__/ValidationBlock.spec.tsx +2 -0
  11. package/src/scripts/dataset/draft-container.tsx +2 -1
  12. package/src/scripts/dataset/files/__tests__/__snapshots__/file-tree.spec.jsx.snap +1 -9
  13. package/src/scripts/dataset/fragments/__tests__/{dataset-alert-draft.spec.tsx → dataset-alert.spec.tsx} +33 -1
  14. package/src/scripts/dataset/fragments/{dataset-alert-draft.tsx → dataset-alert.tsx} +30 -18
  15. package/src/scripts/dataset/routes/delete-page.tsx +72 -39
  16. package/src/scripts/dataset/routes/snapshot.tsx +23 -17
  17. package/src/scripts/dataset/routes/tab-routes-draft.tsx +5 -2
  18. package/src/scripts/dataset/snapshot-container.tsx +11 -0
  19. package/src/scripts/search/__tests__/search-params-ctx.spec.tsx +3 -0
  20. package/src/scripts/search/initial-search-params.tsx +2 -0
  21. package/src/scripts/search/inputs/__tests__/nihselect.spec.tsx +36 -0
  22. package/src/scripts/search/inputs/index.ts +2 -0
  23. package/src/scripts/search/inputs/nih-select.tsx +63 -0
  24. package/src/scripts/search/search-container.tsx +20 -12
  25. package/src/scripts/search/search-params-ctx.tsx +2 -0
  26. package/src/scripts/search/search-routes.tsx +14 -6
  27. package/src/scripts/search/use-search-results.tsx +15 -0
  28. package/src/scripts/types/user-types.ts +72 -0
  29. package/src/scripts/uploader/upload-issues.tsx +2 -2
  30. package/src/scripts/users/__tests__/datasest-card.spec.tsx +201 -0
  31. package/src/scripts/users/__tests__/user-card.spec.tsx +30 -3
  32. package/src/scripts/users/__tests__/user-query.spec.tsx +6 -0
  33. package/src/scripts/users/__tests__/user-routes.spec.tsx +42 -18
  34. package/src/scripts/users/components/user-dataset-filters.tsx +157 -0
  35. package/src/scripts/users/dataset-card.tsx +121 -0
  36. package/src/scripts/users/fragments/query.js +42 -0
  37. package/src/scripts/users/scss/datasetcard.module.scss +153 -0
  38. package/src/scripts/users/scss/usernotifications.module.scss +159 -0
  39. package/src/scripts/users/user-account-view.tsx +1 -12
  40. package/src/scripts/users/user-card.tsx +1 -14
  41. package/src/scripts/users/user-container.tsx +1 -17
  42. package/src/scripts/users/user-datasets-view.tsx +58 -43
  43. package/src/scripts/users/user-notification-accordion.tsx +160 -0
  44. package/src/scripts/users/user-notification-list.tsx +27 -0
  45. package/src/scripts/users/user-notifications-tab-content.tsx +85 -0
  46. package/src/scripts/users/user-notifications-view.tsx +102 -4
  47. package/src/scripts/users/user-query.tsx +6 -14
  48. package/src/scripts/users/user-routes.tsx +18 -19
  49. package/src/scripts/utils/__tests__/user-datasets.spec.tsx +86 -0
  50. package/src/scripts/utils/gtag.js +3 -2
  51. package/src/scripts/utils/user-datasets.tsx +60 -0
  52. package/src/scripts/validation/__tests__/__snapshots__/validation-issues.spec.tsx.snap +1 -122
  53. package/src/scripts/validation/validation-results-query.ts +44 -0
  54. package/src/scripts/validation/validation-results.tsx +31 -7
  55. package/src/scripts/validation/validation.tsx +58 -49
  56. package/src/scripts/workers/schema.worker.ts +2 -7
  57. package/tsconfig.json +1 -2
  58. package/vite.config.js +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openneuro/app",
3
- "version": "4.30.2",
3
+ "version": "4.31.0",
4
4
  "description": "React JS web frontend for the OpenNeuro platform.",
5
5
  "license": "MIT",
6
6
  "main": "public/client.js",
@@ -16,11 +16,11 @@
16
16
  "dependencies": {
17
17
  "@apollo/client": "3.11.8",
18
18
  "@artsy/fresnel": "^1.3.1",
19
- "@bids/validator": "npm:@jsr/bids__validator@^2.0.0",
19
+ "@bids/validator": "npm:@jsr/bids__validator@^2.0.2",
20
20
  "@emotion/react": "11.11.1",
21
21
  "@emotion/styled": "11.11.0",
22
22
  "@niivue/niivue": "0.45.1",
23
- "@openneuro/components": "^4.30.2",
23
+ "@openneuro/components": "^4.31.0",
24
24
  "@sentry/react": "^8.25.0",
25
25
  "@tanstack/react-table": "^8.9.3",
26
26
  "buffer": "^6.0.3",
@@ -68,11 +68,11 @@
68
68
  "sass": "^1.32.8",
69
69
  "stream-browserify": "^3.0.0",
70
70
  "typescript": "5.6.3",
71
- "vite": "5.4.8",
71
+ "vite": "5.4.12",
72
72
  "vitest": "2.1.2"
73
73
  },
74
74
  "publishConfig": {
75
75
  "access": "public"
76
76
  },
77
- "gitHead": "7a6abc827a38daa177038e85fd1130daa810fbd0"
77
+ "gitHead": "428e6902d79ee14a402054cceeaa13fa37192849"
78
78
  }
Binary file
Binary file
Binary file
Binary file
package/src/client.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Browser client entrypoint - see server.tsx for SSR entrypoint
2
+ * Browser client entrypoint
3
3
  */
4
4
  import "./scripts/utils/global-polyfill"
5
5
  import "./scripts/sentry"
@@ -135,13 +135,8 @@ export const DATASET_ISSUES = gql`
135
135
  ${ISSUE_FIELDS}
136
136
  }
137
137
  validation {
138
- codeMessages {
139
- code
140
- message
141
- }
142
- issues {
143
- ${VALIDATION_FIELDS}
144
- }
138
+ errors
139
+ warnings
145
140
  }
146
141
  }
147
142
  }
@@ -154,13 +149,8 @@ export const SNAPSHOT_ISSUES = gql`
154
149
  ${ISSUE_FIELDS}
155
150
  }
156
151
  validation {
157
- codeMessages {
158
- code
159
- message
160
- }
161
- issues {
162
- ${VALIDATION_FIELDS}
163
- }
152
+ errors
153
+ warnings
164
154
  }
165
155
  }
166
156
  `
@@ -181,124 +181,7 @@ exports[`SnapshotContainer component > renders successfully 1`] = `
181
181
  </div>
182
182
  <div
183
183
  class="accordion-item collapsed "
184
- >
185
- <div
186
- class="accordion-content"
187
- >
188
- <div>
189
- <span
190
- class="message error fade-in"
191
- >
192
- We found
193
- <strong>
194
- 1 Warning
195
- </strong>
196
- in your dataset. You are not required to fix warnings, but doing so will make your dataset more BIDS compliant.
197
- </span>
198
- </div>
199
- <br />
200
- <div
201
- class="validation-messages on-accordion-wrapper"
202
- >
203
- <article
204
- class="plain accordion fade-in upload-panel warning-wrap"
205
- >
206
- <div
207
- class="accordion-title "
208
- role="switch"
209
- >
210
- <span>
211
- view 1 warning in 1 file
212
- </span>
213
- </div>
214
- <div
215
- class="accordion-item collapsed "
216
- >
217
- <div
218
- class="accordion-content"
219
- >
220
- <div
221
- class=" on-accordion-wrapper"
222
- >
223
- <article
224
- class="plain accordion validation-error fade-in"
225
- >
226
- <div
227
- class="accordion-title "
228
- role="switch"
229
- >
230
- <span
231
- class="file-header"
232
- >
233
- <h4
234
- class="em-header"
235
- >
236
- <strong
237
- class="em-header "
238
- >
239
- Warning: 1
240
- </strong>
241
- <span
242
- class="file-issue-count"
243
- >
244
- 1 file
245
- </span>
246
- </h4>
247
- Tabular file contains custom columns not described in a data dictionary
248
- </span>
249
- </div>
250
- <div
251
- class="accordion-item collapsed "
252
- >
253
- <div
254
- class="accordion-content"
255
- >
256
- <div
257
- class="em-body"
258
- >
259
- <span
260
- class="e-meta"
261
- >
262
- <span>
263
- <label>
264
- Location:
265
- </label>
266
- <p>
267
- /participants.tsv
268
- </p>
269
- </span>
270
- </span>
271
- <span
272
- class="e-meta"
273
- >
274
- <label>
275
- Reason:
276
- </label>
277
- <p>
278
- Tabular file contains custom columns not described in a data dictionary
279
- </p>
280
- </span>
281
- <span
282
- class="e-meta"
283
- >
284
- <label>
285
- Evidence:
286
- </label>
287
- <p>
288
- Columns: sex, age not defined, please define in: /participants.json
289
- </p>
290
- </span>
291
- </div>
292
- </div>
293
- </div>
294
- </article>
295
- </div>
296
- </div>
297
- </div>
298
- </article>
299
- </div>
300
- </div>
301
- </div>
184
+ />
302
185
  </article>
303
186
  </div>
304
187
  </div>
@@ -670,174 +553,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
670
553
  </div>
671
554
  <div
672
555
  class="accordion-item collapsed "
673
- >
674
- <div
675
- class="accordion-content"
676
- >
677
- <ul
678
- class="child-files"
679
- >
680
- <li
681
- class="clearfix filetree-item filetree-file"
682
- >
683
- <span
684
- aria-label=""
685
- class=" on-icon "
686
- role="img"
687
- style="color: orange;"
688
- >
689
- <i
690
- class="fas fa-file-alt"
691
- />
692
- </span>
693
-   CHANGES
694
- <span
695
- class="filetree-editfile"
696
- />
697
- </li>
698
- <li
699
- class="clearfix filetree-item filetree-file"
700
- >
701
- <span
702
- aria-label=""
703
- class=" on-icon "
704
- role="img"
705
- style="color: deepskyblue;"
706
- >
707
- <i
708
- class="fab fa-markdown"
709
- />
710
- </span>
711
-   README
712
- <span
713
- class="filetree-editfile"
714
- />
715
- </li>
716
- <li
717
- class="clearfix filetree-item filetree-file"
718
- >
719
- <span
720
- aria-label=""
721
- class=" on-icon "
722
- role="img"
723
- style="color: limegreen;"
724
- >
725
- <i
726
- class="fab fa-node-js"
727
- />
728
- </span>
729
-   T1w.json
730
- <span
731
- class="filetree-editfile"
732
- />
733
- </li>
734
- <li
735
- class="clearfix filetree-item filetree-file"
736
- >
737
- <span
738
- aria-label=""
739
- class=" on-icon "
740
- role="img"
741
- style="color: limegreen;"
742
- >
743
- <i
744
- class="fab fa-node-js"
745
- />
746
- </span>
747
-   dataset_description.json
748
- <span
749
- class="filetree-editfile"
750
- />
751
- </li>
752
- <li
753
- class="clearfix filetree-item filetree-file"
754
- >
755
- <span
756
- aria-label=""
757
- class=" on-icon "
758
- role="img"
759
- style="color: lightgreen;"
760
- >
761
- <i
762
- class="fas fa-file-excel"
763
- />
764
- </span>
765
-   participants.tsv
766
- <span
767
- class="filetree-editfile"
768
- />
769
- </li>
770
- <li
771
- class="clearfix filetree-item filetree-dir"
772
- >
773
- <article
774
- class="file-tree accordion "
775
- >
776
- <div
777
- class="accordion-title "
778
- role="switch"
779
- >
780
- <span
781
- aria-label="sub-01"
782
- class="file-icon on-icon icon-text "
783
- role="img"
784
- >
785
- <i
786
- class="fas fa-folder"
787
- />
788
- sub-01
789
- </span>
790
- </div>
791
- <div
792
- class="accordion-item collapsed "
793
- >
794
- <div
795
- class="accordion-content"
796
- >
797
- <div>
798
- Loading...
799
- </div>
800
- </div>
801
- </div>
802
- </article>
803
- </li>
804
- <li
805
- class="clearfix filetree-item filetree-dir"
806
- >
807
- <article
808
- class="file-tree accordion "
809
- >
810
- <div
811
- class="accordion-title "
812
- role="switch"
813
- >
814
- <span
815
- aria-label="sub-02"
816
- class="file-icon on-icon icon-text "
817
- role="img"
818
- >
819
- <i
820
- class="fas fa-folder"
821
- />
822
- sub-02
823
- </span>
824
- </div>
825
- <div
826
- class="accordion-item collapsed "
827
- >
828
- <div
829
- class="accordion-content"
830
- >
831
- <div>
832
- Loading...
833
- </div>
834
- </div>
835
- </div>
836
- </article>
837
- </li>
838
- </ul>
839
- </div>
840
- </div>
556
+ />
841
557
  </article>
842
558
  </div>
843
559
  </div>
@@ -1003,15 +719,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
1003
719
  </div>
1004
720
  <div
1005
721
  class="accordion-item collapsed "
1006
- >
1007
- <div
1008
- class="accordion-content"
1009
- >
1010
- <div>
1011
- Loading...
1012
- </div>
1013
- </div>
1014
- </div>
722
+ />
1015
723
  </article>
1016
724
  </li>
1017
725
  <li
@@ -1037,15 +745,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
1037
745
  </div>
1038
746
  <div
1039
747
  class="accordion-item collapsed "
1040
- >
1041
- <div
1042
- class="accordion-content"
1043
- >
1044
- <div>
1045
- Loading...
1046
- </div>
1047
- </div>
1048
- </div>
748
+ />
1049
749
  </article>
1050
750
  </li>
1051
751
  </ul>
@@ -1,7 +1,6 @@
1
1
  import React from "react"
2
- import { Validation } from "../../validation/validation"
2
+ import { Validation, ValidationPending } from "../../validation/validation"
3
3
  import LegacyValidation from "../../validation-legacy/validation.jsx"
4
- import { DatasetIssues } from "@bids/validator/issues"
5
4
  import type { Issue } from "@bids/validator/issues"
6
5
 
7
6
  // TODO - Generate from GraphQL
@@ -14,10 +13,13 @@ interface CodeMessageInput {
14
13
  interface ValidationFragment {
15
14
  issues: Issue[]
16
15
  codeMessages: CodeMessageInput[]
16
+ warnings: number
17
+ errors: number
17
18
  }
18
19
 
19
20
  export interface ValidationBlockProps {
20
21
  datasetId: string
22
+ version?: string
21
23
  issues?: object
22
24
  validation?: ValidationFragment
23
25
  }
@@ -29,6 +31,7 @@ export interface ValidationBlockProps {
29
31
  */
30
32
  export const ValidationBlock: React.FC<ValidationBlockProps> = ({
31
33
  datasetId,
34
+ version,
32
35
  issues,
33
36
  validation,
34
37
  }) => {
@@ -40,26 +43,21 @@ export const ValidationBlock: React.FC<ValidationBlockProps> = ({
40
43
  )
41
44
  } else {
42
45
  // If data exists, populate this. Otherwise we show pending.
43
- if (validation?.issues) {
44
- // Reconstruct DatasetIssues from JSON
45
- const datasetIssues = new DatasetIssues()
46
- datasetIssues.issues = validation.issues
47
- datasetIssues.codeMessages = validation.codeMessages.reduce(
48
- (acc, curr) => {
49
- acc.set(curr.code, curr.message)
50
- return acc
51
- },
52
- new Map<string, string>(),
53
- )
46
+ if (validation?.warnings + validation?.errors > 0) {
54
47
  return (
55
48
  <div className="validation-accordion">
56
- <Validation issues={datasetIssues} />
49
+ <Validation
50
+ datasetId={datasetId}
51
+ version={version}
52
+ warnings={validation.warnings}
53
+ errors={validation.errors}
54
+ />
57
55
  </div>
58
56
  )
59
57
  } else {
60
58
  return (
61
59
  <div className="validation-accordion">
62
- <Validation issues={null} />
60
+ <ValidationPending />
63
61
  </div>
64
62
  )
65
63
  }
@@ -26,6 +26,8 @@ describe("ValidationBlock component", () => {
26
26
  codeMessages: [
27
27
  { code: "JSON_KEY_RECOMMENDED", message: "message" },
28
28
  ],
29
+ warnings: 1,
30
+ errors: 0,
29
31
  }
30
32
  render(
31
33
  <ValidationBlock
@@ -13,7 +13,7 @@ import {
13
13
  hasEditPermissions,
14
14
  } from "../authentication/profile"
15
15
  import { useCookies } from "react-cookie"
16
- import { DatasetAlertDraft } from "./fragments/dataset-alert-draft"
16
+ import { DatasetAlertDraft } from "./fragments/dataset-alert"
17
17
  import { CloneDropdown } from "./components/CloneDropdown"
18
18
  import { DatasetGitAccess } from "./components/DatasetGitAccess"
19
19
  import { DatasetHeader } from "./components/DatasetHeader"
@@ -135,6 +135,7 @@ const DraftContainer: React.FC<DraftContainerProps> = ({ dataset }) => {
135
135
  <div className="dataset-validation">
136
136
  <ValidationBlock
137
137
  datasetId={dataset.id}
138
+ version={dataset.draft.head}
138
139
  issues={dataset.draft.issues}
139
140
  validation={dataset.draft.validation}
140
141
  />
@@ -21,15 +21,7 @@ exports[`FileTree component > renders with default props 1`] = `
21
21
  </div>
22
22
  <div
23
23
  class="accordion-item collapsed "
24
- >
25
- <div
26
- class="accordion-content"
27
- >
28
- <ul
29
- class="child-files"
30
- />
31
- </div>
32
- </div>
24
+ />
33
25
  </article>
34
26
  </DocumentFragment>
35
27
  `;
@@ -1,7 +1,7 @@
1
1
  import React from "react"
2
2
  import { render, screen } from "@testing-library/react"
3
3
  import { MemoryRouter } from "react-router-dom"
4
- import { DatasetAlertDraft } from "../dataset-alert-draft"
4
+ import { DatasetAlertDraft, DatasetAlertPrivate } from "../dataset-alert"
5
5
 
6
6
  describe("DatasetAlertDraft component", () => {
7
7
  it("renders the correct text for private drafts with changes", () => {
@@ -69,3 +69,35 @@ describe("DatasetAlertDraft component", () => {
69
69
  ).toBeInTheDocument()
70
70
  })
71
71
  })
72
+
73
+ describe("DatasetAlertPrivate component", () => {
74
+ it("renders the correct text for private snapshots with no changes", () => {
75
+ render(
76
+ <DatasetAlertPrivate
77
+ datasetId="test00001"
78
+ hasDraftChanges={false}
79
+ />,
80
+ { wrapper: MemoryRouter },
81
+ )
82
+
83
+ expect(
84
+ screen.queryByText(/this dataset has not been published/i),
85
+ ).toBeInTheDocument()
86
+ expect(
87
+ screen.queryByText(/there have been changes to the draft/i),
88
+ ).not.toBeInTheDocument()
89
+ })
90
+ it("renders the correct text for private snapshots with changes", () => {
91
+ render(
92
+ <DatasetAlertPrivate
93
+ datasetId="test00001"
94
+ hasDraftChanges
95
+ />,
96
+ { wrapper: MemoryRouter },
97
+ )
98
+
99
+ expect(
100
+ screen.queryByText(/there have been changes to the draft/i),
101
+ ).toBeInTheDocument()
102
+ })
103
+ })
@@ -2,6 +2,11 @@ import React from "react"
2
2
  import { Link } from "react-router-dom"
3
3
  import { DatasetAlert } from "../components/DatasetAlert"
4
4
 
5
+ export interface DatasetAlertPrivateProps {
6
+ datasetId: string
7
+ hasDraftChanges: boolean
8
+ }
9
+
5
10
  export interface DatasetAlertDraftProps {
6
11
  isPrivate: boolean
7
12
  datasetId: string
@@ -9,6 +14,30 @@ export interface DatasetAlertDraftProps {
9
14
  hasSnapshot: boolean
10
15
  }
11
16
 
17
+ export const DatasetAlertPrivate: React.FC<DatasetAlertPrivateProps> = ({
18
+ datasetId,
19
+ hasDraftChanges,
20
+ }) => {
21
+ return (
22
+ <DatasetAlert
23
+ alert="This dataset has not been published!"
24
+ footer={hasDraftChanges &&
25
+ "* There have been changes to the draft since your last version"}
26
+ level="warning"
27
+ >
28
+ <>
29
+ <Link
30
+ className="dataset-tool"
31
+ to={"/datasets/" + datasetId + "/publish"}
32
+ >
33
+ Publish this dataset
34
+ </Link>
35
+ &#32; to make all versions available publicly.
36
+ </>
37
+ </DatasetAlert>
38
+ )
39
+ }
40
+
12
41
  export const DatasetAlertDraft: React.FC<DatasetAlertDraftProps> = ({
13
42
  isPrivate,
14
43
  datasetId,
@@ -17,24 +46,7 @@ export const DatasetAlertDraft: React.FC<DatasetAlertDraftProps> = ({
17
46
  }) => {
18
47
  if (isPrivate) {
19
48
  if (hasSnapshot) {
20
- return (
21
- <DatasetAlert
22
- alert="This dataset has not been published!"
23
- footer={hasDraftChanges &&
24
- "* There have been changes to the draft since your last version"}
25
- level="warning"
26
- >
27
- <>
28
- <Link
29
- className="dataset-tool"
30
- to={"/datasets/" + datasetId + "/publish"}
31
- >
32
- Publish this dataset
33
- </Link>
34
- &#32; to make all versions available publicly.
35
- </>
36
- </DatasetAlert>
37
- )
49
+ return DatasetAlertPrivate({ datasetId, hasDraftChanges })
38
50
  } else {
39
51
  return (
40
52
  <DatasetAlert