@openneuro/app 4.15.2-demo.1 → 4.16.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.15.2-demo.1",
3
+ "version": "4.16.0",
4
4
  "description": "React JS web frontend for the OpenNeuro platform.",
5
5
  "license": "MIT",
6
6
  "main": "public/client.js",
@@ -20,9 +20,9 @@
20
20
  "@emotion/react": "11.6.0",
21
21
  "@emotion/styled": "11.6.0",
22
22
  "@niivue/niivue": "0.23.1",
23
- "@openneuro/client": "^4.15.2-demo.1",
24
- "@openneuro/components": "^4.15.2-demo.1",
25
- "bids-validator": "1.9.9",
23
+ "@openneuro/client": "^4.16.0",
24
+ "@openneuro/components": "^4.16.0",
25
+ "bids-validator": "1.10.0",
26
26
  "bytes": "^3.0.0",
27
27
  "comlink": "^4.0.5",
28
28
  "date-fns": "^2.16.1",
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "38094ea1b60e11a55425dbe597a10d872a4cb89e"
84
+ "gitHead": "e058ca8a6eda436e3c24cb4bc36579197d36aa79"
85
85
  }
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+ import { useCookies } from 'react-cookie'
3
+ import { getProfile } from './profile.js'
4
+
5
+ interface RegularUserProps {
6
+ children?: React.ReactNode
7
+ }
8
+
9
+ /**
10
+ * Render children if this is not an admin user
11
+ */
12
+ export const RegularUser = ({ children }: RegularUserProps): JSX.Element => {
13
+ const [cookies] = useCookies()
14
+ const profile = getProfile(cookies)
15
+ if (profile?.admin) {
16
+ return null
17
+ } else {
18
+ return <>{children}</>
19
+ }
20
+ }
@@ -162,6 +162,14 @@ export const DatasetQueryHook = ({ datasetId, draft }) => {
162
162
  if (error.message === 'You do not have access to read this dataset.') {
163
163
  return <FourOThreePage />
164
164
  } else if (error.message.includes('has been deleted')) {
165
+ for (const err of error.graphQLErrors) {
166
+ if (
167
+ err.extensions.code === 'DELETED_DATASET' &&
168
+ err.extensions.redirect
169
+ ) {
170
+ navigate(err.extensions.redirect)
171
+ }
172
+ }
165
173
  return <FourOFourPage message={error.message} />
166
174
  } else {
167
175
  try {
@@ -3,7 +3,9 @@ import { useCookies } from 'react-cookie'
3
3
  import DeleteDatasetForm from '../mutations/delete-dataset-form.jsx'
4
4
  import DeleteDataset from '../mutations/delete.jsx'
5
5
  import LoggedIn from '../../authentication/logged-in.jsx'
6
- import { hasEditPermissions, getProfile } from '../../authentication/profile.js'
6
+ import { getProfile } from '../../authentication/profile.js'
7
+ import AdminUser from '../../authentication/admin-user.jsx'
8
+ import { RegularUser } from '../../authentication/regular-user'
7
9
  import { DatasetPageBorder } from './styles/dataset-page-border'
8
10
  import { HeaderRow3 } from './styles/header-row'
9
11
 
@@ -28,30 +30,38 @@ const DeletePage = ({ dataset }: DeletePageProps): React.ReactElement => {
28
30
  }
29
31
  const [cookies] = useCookies()
30
32
  const user = getProfile(cookies)
31
- const hasEdit =
32
- (user && user.admin) ||
33
- hasEditPermissions(dataset.permissions, user && user.sub)
33
+ const hasEdit = user && user.admin
34
34
  const datasetId = dataset.id
35
35
  return (
36
36
  <DatasetPageBorder>
37
37
  <HeaderRow3>Delete Dataset</HeaderRow3>
38
- <DeleteDatasetForm
39
- values={values}
40
- onChange={handleInputChange}
41
- hideDisabled={false}
42
- hasEdit={hasEdit}
43
- />
44
- <p>
45
- <small className="warning-text">
46
- * Warning: this action will permanently remove this dataset along with
47
- associated snapshots.
48
- </small>
49
- </p>
50
- <div className=" dataset-form-controls">
51
- <LoggedIn>
52
- <DeleteDataset datasetId={datasetId} metadata={values} />
53
- </LoggedIn>
54
- </div>
38
+ <AdminUser>
39
+ <DeleteDatasetForm
40
+ values={values}
41
+ onChange={handleInputChange}
42
+ hideDisabled={false}
43
+ hasEdit={hasEdit}
44
+ />
45
+ <p>
46
+ <small className="warning-text">
47
+ * Warning: this action will permanently remove this dataset along
48
+ with associated snapshots.
49
+ </small>
50
+ </p>
51
+ <div className="dataset-form-controls">
52
+ <LoggedIn>
53
+ <DeleteDataset datasetId={datasetId} metadata={values} />
54
+ </LoggedIn>
55
+ </div>
56
+ </AdminUser>
57
+ <RegularUser>
58
+ <p>
59
+ Please contact support to permanently remove a dataset and all
60
+ versions of it. Provide a reason for the removal request and if the
61
+ dataset is a duplicate or has been supplanted by another provide that
62
+ information for a redirect to be created.
63
+ </p>
64
+ </RegularUser>
55
65
  </DatasetPageBorder>
56
66
  )
57
67
  }
@@ -65,7 +65,7 @@ class UploadValidator extends React.Component {
65
65
  }
66
66
  const options = {
67
67
  config: {
68
- error: ['NO_AUTHORS'],
68
+ error: ['NO_AUTHORS', 'EMPTY_DATASET_NAME'],
69
69
  ignoreSubjectConsistency: true,
70
70
  blacklistModalities: ['Microscopy'],
71
71
  },
@@ -11,7 +11,7 @@ class Issues extends React.Component {
11
11
  render() {
12
12
  const issueFiles = this.props.issues
13
13
  const issues = issueFiles.map((issue, index) => {
14
- let totalFiles = issue.files.length || issue.files.size
14
+ let totalFiles = issue.files.length
15
15
  if (issue.additionalFileCount) {
16
16
  totalFiles += issue.additionalFileCount
17
17
  }
@@ -32,7 +32,7 @@ class Issues extends React.Component {
32
32
  )
33
33
 
34
34
  // issue sub-errors
35
- const subErrors = Array.from(issue.files).map((error, index2) => {
35
+ const subErrors = issue.files.map((error, index2) => {
36
36
  return error ? (
37
37
  <Issue
38
38
  type={this.props.issueType}
@@ -78,7 +78,7 @@ class ValidationResults extends React.Component {
78
78
  _countFiles(issues) {
79
79
  let numFiles = 0
80
80
  for (const issue of issues) {
81
- numFiles += Array.from(issue.files).length
81
+ numFiles += issue.files.length
82
82
  if (issue.additionalFileCount) {
83
83
  numFiles += issue.additionalFileCount
84
84
  }
@@ -1,25 +1,22 @@
1
1
  /* eslint-env worker */
2
- import { validate, fileListToTree } from '../utils/schema-validator.js'
2
+ import validate from 'bids-validator'
3
3
  import { BIDSValidatorIssues } from './worker-interface'
4
4
 
5
+ const asyncValidateBIDS = (files, options): Promise<BIDSValidatorIssues> =>
6
+ new Promise(resolve => {
7
+ validate.BIDS(files, options, (issues, summary) =>
8
+ resolve({ issues, summary }),
9
+ )
10
+ })
11
+
5
12
  export async function runValidator(
6
13
  files,
7
14
  options,
8
15
  cb,
9
16
  ): Promise<BIDSValidatorIssues> {
10
17
  let error, output: BIDSValidatorIssues
11
- output = { issues: { errors: [], warnings: [] }, summary: {} }
12
18
  try {
13
- const tree = await fileListToTree(files)
14
- const result = await validate(tree, { json: true })
15
- const issues = Array.from(result.issues, ([key, value]) => value)
16
- console.log(issues)
17
- output.issues.warnings = issues.filter(
18
- issue => issue.severity === 'warning',
19
- )
20
- output.issues.errors = issues.filter(issue => issue.severity === 'error')
21
- output.summary = result.summary
22
- console.log(output)
19
+ output = await asyncValidateBIDS(files, options)
23
20
  } catch (err) {
24
21
  error = err
25
22
  }
@@ -1,8 +1,5 @@
1
1
  // Shared interface for BIDSValidatorIssues shared without cross import for validate and validate.worker
2
2
  export interface BIDSValidatorIssues {
3
- issues: {
4
- errors: Record<string, unknown>[]
5
- warnings: Record<string, unknown>[]
6
- }
3
+ issues: Record<string, unknown>[]
7
4
  summary: Record<string, unknown>
8
5
  }
package/vite.config.js CHANGED
@@ -7,7 +7,6 @@ export default defineConfig({
7
7
  server: {
8
8
  port: 80,
9
9
  host: '0.0.0.0',
10
- cors: true,
11
10
  },
12
11
  build: {
13
12
  sourcemap: true,